Skip to content

Commit cd0ab02

Browse files
authored
Merge pull request #41
Simplified the syntax for registration of randomization rules
2 parents 7016e53 + 0c2da4f commit cd0ab02

File tree

8 files changed

+98
-95
lines changed

8 files changed

+98
-95
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ public class PersonRandomizer : ComplexRandomizer<Person>
9898
{
9999
public PersonRandomizer()
100100
{
101-
this.AddRandomizationRule(p => p.Id, new GuidRandomizer());
102-
this.AddRandomizationRule(p => p.Name, new StringRandomizer());
103-
this.AddRandomizationRule(p => p.Age, new NumberRandomizer());
104-
this.AddRandomizationRule(p => p.IsEmployed, new BooleanRandomizer());
105-
this.AddRandomizationRule(p => p.EventDate, new DateTimeOffsetRandomizer());
101+
this.Randomize(p => p.Id, new GuidRandomizer());
102+
this.Randomize(p => p.Name, new StringRandomizer());
103+
this.Randomize(p => p.Age, new NumberRandomizer());
104+
this.Randomize(p => p.IsEmployed, new BooleanRandomizer());
105+
this.Randomize(p => p.EventDate, new DateTimeOffsetRandomizer());
106106
}
107107
}
108108
```
@@ -161,5 +161,4 @@ The order will be preserved - the value setter of a given randomization rule wil
161161

162162
- We do not recommend using `complex randomizers` with abstract classes or interfaces.
163163
While it is possible to make such a setup work, there may be some intricacies along the way.
164-
The `AddRandomizationRule` and `OverrideRandomizationRule` methods are publicly exposed so extension methods can be extracted (or even inheritance will get the job done for some simple cases).
165164
Another idea that is especially useful when dealing with many derived types that have behavioral but not structural differences, is to make the `complex randomizer` generic.

src/TryAtSoftware.Randomizer.Core/ComplexRandomizer.cs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
using System;
44
using System.Collections.Generic;
5+
using System.Linq.Expressions;
56
using TryAtSoftware.Randomizer.Core.Interfaces;
67

7-
public class ComplexRandomizer<TEntity> : IComplexRandomizer<TEntity>
8+
public class ComplexRandomizer<TEntity> : IConfigurableComplexRandomizer<TEntity>
89
{
910
private readonly List<string> _orderedMembers = new ();
1011
private readonly HashSet<string> _randomizedMembers = new ();
@@ -24,20 +25,6 @@ public ComplexRandomizer(IInstanceBuilder<TEntity> instanceBuilder)
2425
/// <inheritdoc />
2526
public IInstanceBuilder<TEntity> InstanceBuilder { get; }
2627

27-
/// <inheritdoc />
28-
public void AddRandomizationRule(IRandomizationRule<TEntity> rule)
29-
{
30-
if (string.IsNullOrWhiteSpace(rule.PropertyName) || this._randomizedMembers.Contains(rule.PropertyName)) return;
31-
this.SetRuleInternally(rule);
32-
}
33-
34-
/// <inheritdoc />
35-
public void OverrideRandomizationRule(IRandomizationRule<TEntity> rule)
36-
{
37-
if (string.IsNullOrWhiteSpace(rule.PropertyName)) return;
38-
this.SetRuleInternally(rule);
39-
}
40-
4128
/// <inheritdoc />
4229
public TEntity PrepareRandomValue()
4330
{
@@ -55,6 +42,31 @@ public TEntity PrepareRandomValue()
5542
return instance;
5643
}
5744

45+
/// <inheritdoc />
46+
public void Randomize(IRandomizationRule<TEntity> rule)
47+
{
48+
if (rule is null) throw new ArgumentNullException(nameof(rule));
49+
this.SetRuleInternally(rule);
50+
}
51+
52+
/// <inheritdoc />
53+
public void Randomize<TValue>(Expression<Func<TEntity, TValue>> propertySelector, IRandomizer<TValue> randomizer)
54+
{
55+
if (propertySelector is null) throw new ArgumentNullException(nameof(propertySelector));
56+
if (randomizer is null) throw new ArgumentNullException(nameof(randomizer));
57+
58+
this.SetRuleInternally(new RandomizationRule<TEntity,TValue>(propertySelector, randomizer));
59+
}
60+
61+
/// <inheritdoc />
62+
public void Randomize<TValue>(Expression<Func<TEntity, TValue>> propertySelector, Func<TEntity, IRandomizer<TValue>?> getRandomizer)
63+
{
64+
if (propertySelector is null) throw new ArgumentNullException(nameof(propertySelector));
65+
if (getRandomizer is null) throw new ArgumentNullException(nameof(getRandomizer));
66+
67+
this.SetRuleInternally(new RandomizationRule<TEntity,TValue>(propertySelector, getRandomizer));
68+
}
69+
5870
private void SetRuleInternally(IRandomizationRule<TEntity> rule)
5971
{
6072
if (string.IsNullOrWhiteSpace(rule.PropertyName)) return;

src/TryAtSoftware.Randomizer.Core/Helpers/ExpressionsHelper.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
namespace TryAtSoftware.Randomizer.Core.Interfaces;
22

3+
using System;
4+
using System.Linq.Expressions;
5+
36
public interface IComplexRandomizer<out TEntity> : IRandomizer<TEntity>
47
{
58
IInstanceBuilder<TEntity> InstanceBuilder { get; }
9+
}
610

7-
void AddRandomizationRule(IRandomizationRule<TEntity> rule);
8-
void OverrideRandomizationRule(IRandomizationRule<TEntity> rule);
11+
public interface IConfigurableComplexRandomizer<TEntity> : IComplexRandomizer<TEntity>
12+
{
13+
void Randomize(IRandomizationRule<TEntity> rule);
14+
void Randomize<TValue>(Expression<Func<TEntity, TValue>> propertySelector, IRandomizer<TValue> randomizer);
15+
void Randomize<TValue>(Expression<Func<TEntity, TValue>> propertySelector, Func<TEntity, IRandomizer<TValue>?> getRandomizer);
916
}
Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,9 @@
11
namespace TryAtSoftware.Randomizer.Core;
22

3-
using System;
4-
using System.Linq.Expressions;
53
using TryAtSoftware.Randomizer.Core.Interfaces;
64
using TryAtSoftware.Randomizer.Core.Primitives;
75

86
public static class RandomizationExtensions
97
{
108
public static IRandomizer<TValue> AsConstantRandomizer<TValue>(this TValue value) => new ConstantValueRandomizer<TValue>(value);
11-
12-
public static void AddRandomizationRule<TEntity, TValue>(
13-
this IComplexRandomizer<TEntity> complexRandomizer,
14-
Expression<Func<TEntity, TValue>> propertySelector,
15-
IRandomizer<TValue> randomizer)
16-
{
17-
var rule = BuildRandomizationRule(propertySelector, randomizer);
18-
complexRandomizer.AddRandomizationRule(rule);
19-
}
20-
21-
public static void AddRandomizationRule<TEntity, TValue>(
22-
this IComplexRandomizer<TEntity> complexRandomizer,
23-
Expression<Func<TEntity, TValue>> propertySelector,
24-
Func<TEntity, IRandomizer<TValue>?> getRandomizer)
25-
{
26-
var rule = BuildRandomizationRule(propertySelector, getRandomizer);
27-
complexRandomizer.AddRandomizationRule(rule);
28-
}
29-
30-
public static void OverrideRandomizationRule<TEntity, TValue>(
31-
this IComplexRandomizer<TEntity> complexRandomizer,
32-
Expression<Func<TEntity, TValue>> propertySelector,
33-
IRandomizer<TValue> randomizer)
34-
{
35-
var rule = BuildRandomizationRule(propertySelector, randomizer);
36-
complexRandomizer.OverrideRandomizationRule(rule);
37-
}
38-
39-
public static void OverrideRandomizationRule<TEntity, TValue>(
40-
this IComplexRandomizer<TEntity> complexRandomizer,
41-
Expression<Func<TEntity, TValue>> propertySelector,
42-
Func<TEntity, IRandomizer<TValue>?> getRandomizer)
43-
{
44-
var rule = BuildRandomizationRule(propertySelector, getRandomizer);
45-
complexRandomizer.OverrideRandomizationRule(rule);
46-
}
47-
48-
private static IRandomizationRule<TEntity> BuildRandomizationRule<TEntity, TValue>(Expression<Func<TEntity, TValue>> propertySelector, IRandomizer<TValue> randomizer)
49-
=> new RandomizationRule<TEntity, TValue>(propertySelector, randomizer);
50-
51-
private static IRandomizationRule<TEntity> BuildRandomizationRule<TEntity, TValue>(Expression<Func<TEntity, TValue>> propertySelector, Func<TEntity, IRandomizer<TValue>?> getRandomizer)
52-
=> new RandomizationRule<TEntity, TValue>(propertySelector, getRandomizer);
539
}

src/TryAtSoftware.Randomizer.Core/RandomizationRule.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using System;
44
using System.Linq.Expressions;
5-
using TryAtSoftware.Randomizer.Core.Helpers;
5+
using TryAtSoftware.Extensions.Reflection;
66
using TryAtSoftware.Randomizer.Core.Interfaces;
77
using TryAtSoftware.Randomizer.Core.Primitives;
88

@@ -52,7 +52,7 @@ private static string ExtractPropertyName(Expression<Func<TEntity, TValue>> prop
5252
{
5353
if (propertySelector is null) throw new ArgumentNullException(nameof(propertySelector));
5454

55-
var property = propertySelector.GetPropertyInfo();
56-
return property.Name;
55+
var memberInfo = propertySelector.GetMemberInfo();
56+
return memberInfo.Name;
5757
}
5858
}

tests/TryAtSoftware.Randomizer.Core.Tests/ComplexInitialization/ComplexInitializationTests.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ public void ComplexRandomizerShouldWorkCorrectly()
1717
{
1818
var instanceBuilder = new PersonInstanceBuilder();
1919
var complexRandomizer = new ComplexRandomizer<Person>(instanceBuilder);
20-
complexRandomizer.AddRandomizationRule(p => p.Id, new GuidRandomizer());
21-
complexRandomizer.AddRandomizationRule(p => p.Name, new StringRandomizer());
22-
complexRandomizer.AddRandomizationRule(p => p.Age, new NumberRandomizer());
23-
complexRandomizer.AddRandomizationRule(p => p.IsEmployed, new BooleanRandomizer());
24-
complexRandomizer.AddRandomizationRule(p => p.EventDate, new DateTimeOffsetRandomizer());
20+
complexRandomizer.Randomize(p => p.Id, new GuidRandomizer());
21+
complexRandomizer.Randomize(p => p.Name, new StringRandomizer());
22+
complexRandomizer.Randomize(p => p.Age, new NumberRandomizer());
23+
complexRandomizer.Randomize(p => p.IsEmployed, new BooleanRandomizer());
24+
complexRandomizer.Randomize(p => p.EventDate, new DateTimeOffsetRandomizer());
2525

2626
var firstPerson = complexRandomizer.PrepareRandomValue();
2727
Assert.NotNull(firstPerson);
@@ -35,9 +35,9 @@ public void ComplexRandomizerShouldWorkCorrectly()
3535
public void ComplexInstanceBuildingProcessShouldBeExecutedCorrectly()
3636
{
3737
var complexRandomizer = new ComplexRandomizer<Car>();
38-
complexRandomizer.AddRandomizationRule(x => x.Make, new StringRandomizer());
39-
complexRandomizer.AddRandomizationRule(x => x.Model, new StringRandomizer());
40-
complexRandomizer.AddRandomizationRule(x => x.Year, new NumberRandomizer());
38+
complexRandomizer.Randomize(x => x.Make, new StringRandomizer());
39+
complexRandomizer.Randomize(x => x.Model, new StringRandomizer());
40+
complexRandomizer.Randomize(x => x.Year, new NumberRandomizer());
4141

4242
var firstCar = complexRandomizer.PrepareRandomValue();
4343
Assert.NotNull(firstCar);
@@ -83,7 +83,7 @@ public void OrderOfRandomizationRulesShouldBeAccepted()
8383
for (var j = 0; j < randomizationRuleBuilders.Count; j++)
8484
{
8585
var rule = randomizationRuleBuilders[j].Invoke(valueSetters[valueSetterIndices[j]]);
86-
complexRandomizer.AddRandomizationRule(rule);
86+
complexRandomizer.Randomize(rule);
8787
}
8888

8989
var person = complexRandomizer.PrepareRandomValue();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace TryAtSoftware.Randomizer.Core.Tests;
2+
3+
using System;
4+
using TryAtSoftware.Randomizer.Core.Primitives;
5+
using TryAtSoftware.Randomizer.Core.Tests.Models;
6+
using Xunit;
7+
8+
public class ComplexRandomizerTests
9+
{
10+
[Fact]
11+
public void RandomizeShouldThrowExceptionWhenInvalidParametersAreProvided()
12+
{
13+
var randomizer = new ComplexRandomizer<Person>();
14+
Assert.Throws<ArgumentNullException>(() => randomizer.Randomize(null!));
15+
Assert.Throws<ArgumentNullException>(() => randomizer.Randomize(null!, new StringRandomizer()));
16+
Assert.Throws<ArgumentNullException>(() => randomizer.Randomize<string>(x => x.Name, randomizer: null!));
17+
Assert.Throws<ArgumentNullException>(() => randomizer.Randomize(null!, _ => new StringRandomizer()));
18+
Assert.Throws<ArgumentNullException>(() => randomizer.Randomize<string>(x => x.Name, getRandomizer: null!));
19+
}
20+
21+
[Fact]
22+
public void RandomizationRulesShouldBeAddedSuccessfully()
23+
{
24+
var randomizer = new ComplexRandomizer<Person>();
25+
randomizer.Randomize(x => x.Id, new GuidRandomizer());
26+
randomizer.Randomize(x => x.Name, _ => new StringRandomizer());
27+
randomizer.Randomize(new RandomizationRule<Person, int>(x => x.Age, new NumberRandomizer(min: 10, max: 50)));
28+
29+
var person = randomizer.PrepareRandomValue();
30+
Assert.NotEqual(Guid.Empty, person.Id);
31+
Assert.False(string.IsNullOrWhiteSpace(person.Name));
32+
Assert.NotEqual(0, person.Age);
33+
}
34+
35+
[Fact]
36+
public void RandomizationRulesShouldBeOverriddenSuccessfully()
37+
{
38+
var randomizer = new ComplexRandomizer<Person>();
39+
randomizer.Randomize(x => x.Age, new NumberRandomizer(min: 10, max: 20));
40+
randomizer.Randomize(x => x.Age, new NumberRandomizer(min: 100, max: 200));
41+
42+
var person = randomizer.PrepareRandomValue();
43+
Assert.True(100 <= person.Age && person.Age < 200);
44+
}
45+
}

0 commit comments

Comments
 (0)