Skip to content

Commit 1c82e62

Browse files
committed
Example: A 'fixed' of tracking the context
1 parent 022e08c commit 1c82e62

File tree

3 files changed

+101
-13
lines changed

3 files changed

+101
-13
lines changed

src/AutoFaker{T}.cs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
45
using Bogus;
@@ -19,6 +20,9 @@ public class AutoFaker<TType> : Faker<TType> where TType : class
1920
{
2021
public AutoFakerConfig Config { get; set; }
2122

23+
private ConcurrentDictionary<int, AutoFakerContext> ContextLoopUp { get; } = new();
24+
25+
2226
/// <summary>
2327
/// The <see cref="AutoFakerBinder"/> instance to use for the generation request.
2428
/// </summary>
@@ -63,14 +67,23 @@ public override TType Generate(string? ruleSets = null)
6367
{
6468
Initialize();
6569

66-
AutoFakerContext context = CreateContext(ruleSets);
70+
CreateGenerateContext(ruleSets);
6771

68-
PrepareCreate(context);
69-
PrepareFinish(context);
72+
PrepareCreate();
73+
PrepareFinish();
7074

7175
return base.Generate(ruleSets);
7276
}
7377

78+
private void CreateGenerateContext(string? ruleSets)
79+
{
80+
lock (ContextLoopUp)
81+
{
82+
// Think 1 needs to be added since the generate method increments the context
83+
ContextLoopUp[FakerHub.IndexFaker+1] = CreateContext(ruleSets);
84+
}
85+
}
86+
7487
/// <summary>
7588
/// Generates a collection of instances of type <typeparamref name="TType"/>.
7689
/// </summary>
@@ -81,10 +94,10 @@ public override List<TType> Generate(int count, string? ruleSets = null)
8194
{
8295
Initialize();
8396

84-
AutoFakerContext context = CreateContext(ruleSets);
85-
86-
PrepareCreate(context);
87-
PrepareFinish(context);
97+
CreateGenerateContext(ruleSets);
98+
99+
PrepareCreate();
100+
PrepareFinish();
88101

89102
return base.Generate(count, ruleSets);
90103
}
@@ -96,8 +109,8 @@ public override List<TType> Generate(int count, string? ruleSets = null)
96109
/// <param name="ruleSets">An optional list of delimited rule sets to use for the populate request.</param>
97110
public override void Populate(TType instance, string? ruleSets = null)
98111
{
99-
AutoFakerContext context = CreateContext(ruleSets);
100-
PrepareFinish(context);
112+
CreateGenerateContext(ruleSets);
113+
PrepareFinish();
101114

102115
base.Populate(instance, ruleSets);
103116
}
@@ -141,14 +154,24 @@ private List<string> ParseRuleSets(string? ruleSets)
141154
return validRuleSets;
142155
}
143156

144-
private void PrepareCreate(AutoFakerContext context)
157+
protected AutoFakerContext GetContext(Faker fakerHub)
158+
{
159+
if (!ContextLoopUp.TryGetValue(fakerHub.IndexFaker, out var context))
160+
throw new Exception("I done F'd up");
161+
162+
return context;
163+
}
164+
165+
private void PrepareCreate()
145166
{
146167
// Check a create handler hasn't previously been set or configured externally
147168
if (_createInitialized || CreateActions[currentRuleSet] != null)
148169
return;
149170

150171
CreateActions[currentRuleSet] = faker =>
151172
{
173+
var context = GetContext(faker);
174+
152175
// Only auto create if the 'default' rule set is defined for generation
153176
// This is because any specific rule sets are expected to handle the full creation
154177
if (context.RuleSets != null && context.RuleSets.Contains(currentRuleSet))
@@ -198,7 +221,7 @@ private void PrepareCreate(AutoFakerContext context)
198221
_createInitialized = true;
199222
}
200223

201-
private void PrepareFinish(AutoFakerContext context)
224+
private void PrepareFinish()
202225
{
203226
if (_finishInitialized)
204227
return;
@@ -207,6 +230,8 @@ private void PrepareFinish(AutoFakerContext context)
207230

208231
FinishWith((faker, instance) =>
209232
{
233+
var context = GetContext(faker);
234+
210235
if (instance == null)
211236
return;
212237

test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using FluentAssertions;
1+
using System;
2+
using FluentAssertions;
23
using Soenneker.Utils.AutoBogus.Tests.Dtos.Complex;
34
using System.Collections.Generic;
45
using System.Diagnostics;
@@ -10,6 +11,9 @@
1011
using System.Reflection;
1112
using Soenneker.Reflection.Cache.Options;
1213
using Soenneker.Utils.AutoBogus.Config;
14+
using Soenneker.Utils.AutoBogus.Context;
15+
using Soenneker.Utils.AutoBogus.Generators;
16+
using Soenneker.Utils.AutoBogus.Override;
1317
using Soenneker.Utils.AutoBogus.Tests.Dtos;
1418

1519
namespace Soenneker.Utils.AutoBogus.Tests;
@@ -349,6 +353,65 @@ public void Generate_ImmutableArray_should_generate()
349353
immutableListDto.Array.Should().NotBeNullOrEmpty();
350354
}
351355

356+
357+
public sealed class ExampleClass
358+
{
359+
public string? Value { get; init; }
360+
public string AlwaysSet { get; init; }
361+
}
362+
363+
[Fact]
364+
public void Generate_RulesSet_Should_Generate_Wtih_Ruleset_And_Oeverride()
365+
{
366+
var faker = new ExampleClassFaker();
367+
368+
var withSetNull = faker.Generate("setnull,default");
369+
370+
withSetNull.AlwaysSet.Should().NotBeEmpty();
371+
withSetNull.Value.Should().BeNull();
372+
}
373+
374+
[Fact]
375+
public void Generate_RulesSet_Should_Generate_With_Custom_Faker()
376+
{
377+
var faker = new ExampleClassFaker();
378+
379+
var noRuleSets = faker.Generate();
380+
var setNull = faker.Generate("setnull");
381+
var setNullAndDefault = faker.Generate("setnull,default");
382+
383+
noRuleSets.AlwaysSet.Should().NotBeEmpty();
384+
noRuleSets.Value.Should().NotBeEmpty();
385+
386+
setNull.AlwaysSet.Should().BeNull(); // <-- this is why I use both the default and set null ruleset
387+
setNull.Value.Should().BeNull();
388+
389+
setNullAndDefault.AlwaysSet.Should().NotBeEmpty();
390+
setNullAndDefault.Value.Should().BeNull();
391+
}
392+
393+
public class StringOverride : AutoFakerOverride<string>
394+
{
395+
public override void Generate(AutoFakerOverrideContext context)
396+
{
397+
context.Instance = BuildStringWithPrefix(context.GenerateName);
398+
}
399+
400+
public static string BuildStringWithPrefix(string prefix) =>
401+
$"{prefix}-{Guid.NewGuid().ToString()}";
402+
}
403+
404+
public sealed class ExampleClassFaker : AutoFaker<ExampleClass>
405+
{
406+
public ExampleClassFaker()
407+
{
408+
Config.Overrides ??= new List<AutoFakerGeneratorOverride>();
409+
Config.Overrides.Add(new StringOverride());
410+
411+
RuleSet("setnull", set => set.RuleFor(property => property.Value, () => null));
412+
}
413+
}
414+
352415
[Fact]
353416
public void Generate_TestClassWithAbstractClassParameter_should_generate()
354417
{

test/Soenneker.Utils.AutoBogus.Tests/Dtos/ProductCode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
public sealed class ProductCode
44
{
55
public string SerialNumber { get; set; }
6-
}
6+
}

0 commit comments

Comments
 (0)