diff --git a/src/AutoFaker{T}.cs b/src/AutoFaker{T}.cs index c2eb923..aacd496 100644 --- a/src/AutoFaker{T}.cs +++ b/src/AutoFaker{T}.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Bogus; @@ -19,6 +20,9 @@ public class AutoFaker : Faker where TType : class { public AutoFakerConfig Config { get; set; } + private ConcurrentDictionary ContextLoopUp { get; } = new(); + + /// /// The instance to use for the generation request. /// @@ -63,14 +67,23 @@ public override TType Generate(string? ruleSets = null) { Initialize(); - AutoFakerContext context = CreateContext(ruleSets); + CreateGenerateContext(ruleSets); - PrepareCreate(context); - PrepareFinish(context); + PrepareCreate(); + PrepareFinish(); return base.Generate(ruleSets); } + private void CreateGenerateContext(string? ruleSets) + { + lock (ContextLoopUp) + { + // Think 1 needs to be added since the generate method increments the context + ContextLoopUp[FakerHub.IndexFaker+1] = CreateContext(ruleSets); + } + } + /// /// Generates a collection of instances of type . /// @@ -81,10 +94,10 @@ public override List Generate(int count, string? ruleSets = null) { Initialize(); - AutoFakerContext context = CreateContext(ruleSets); - - PrepareCreate(context); - PrepareFinish(context); + CreateGenerateContext(ruleSets); + + PrepareCreate(); + PrepareFinish(); return base.Generate(count, ruleSets); } @@ -96,8 +109,8 @@ public override List Generate(int count, string? ruleSets = null) /// An optional list of delimited rule sets to use for the populate request. public override void Populate(TType instance, string? ruleSets = null) { - AutoFakerContext context = CreateContext(ruleSets); - PrepareFinish(context); + CreateGenerateContext(ruleSets); + PrepareFinish(); base.Populate(instance, ruleSets); } @@ -141,7 +154,15 @@ private List ParseRuleSets(string? ruleSets) return validRuleSets; } - private void PrepareCreate(AutoFakerContext context) + protected AutoFakerContext GetContext(Faker fakerHub) + { + if (!ContextLoopUp.TryGetValue(fakerHub.IndexFaker, out var context)) + throw new Exception("I done F'd up"); + + return context; + } + + private void PrepareCreate() { // Check a create handler hasn't previously been set or configured externally if (_createInitialized || CreateActions[currentRuleSet] != null) @@ -149,6 +170,8 @@ private void PrepareCreate(AutoFakerContext context) CreateActions[currentRuleSet] = faker => { + var context = GetContext(faker); + // Only auto create if the 'default' rule set is defined for generation // This is because any specific rule sets are expected to handle the full creation if (context.RuleSets != null && context.RuleSets.Contains(currentRuleSet)) @@ -198,7 +221,7 @@ private void PrepareCreate(AutoFakerContext context) _createInitialized = true; } - private void PrepareFinish(AutoFakerContext context) + private void PrepareFinish() { if (_finishInitialized) return; @@ -207,6 +230,8 @@ private void PrepareFinish(AutoFakerContext context) FinishWith((faker, instance) => { + var context = GetContext(faker); + if (instance == null) return; diff --git a/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs b/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs index 0283ac4..6b16f73 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/AutoFakerTests.cs @@ -1,4 +1,5 @@ -using FluentAssertions; +using System; +using FluentAssertions; using Soenneker.Utils.AutoBogus.Tests.Dtos.Complex; using System.Collections.Generic; using System.Diagnostics; @@ -10,6 +11,9 @@ using System.Reflection; using Soenneker.Reflection.Cache.Options; using Soenneker.Utils.AutoBogus.Config; +using Soenneker.Utils.AutoBogus.Context; +using Soenneker.Utils.AutoBogus.Generators; +using Soenneker.Utils.AutoBogus.Override; using Soenneker.Utils.AutoBogus.Tests.Dtos; namespace Soenneker.Utils.AutoBogus.Tests; @@ -349,6 +353,65 @@ public void Generate_ImmutableArray_should_generate() immutableListDto.Array.Should().NotBeNullOrEmpty(); } + + public sealed class ExampleClass + { + public string? Value { get; init; } + public string AlwaysSet { get; init; } + } + + [Fact] + public void Generate_RulesSet_Should_Generate_Wtih_Ruleset_And_Oeverride() + { + var faker = new ExampleClassFaker(); + + var withSetNull = faker.Generate("setnull,default"); + + withSetNull.AlwaysSet.Should().NotBeEmpty(); + withSetNull.Value.Should().BeNull(); + } + + [Fact] + public void Generate_RulesSet_Should_Generate_With_Custom_Faker() + { + var faker = new ExampleClassFaker(); + + var noRuleSets = faker.Generate(); + var setNull = faker.Generate("setnull"); + var setNullAndDefault = faker.Generate("setnull,default"); + + noRuleSets.AlwaysSet.Should().NotBeEmpty(); + noRuleSets.Value.Should().NotBeEmpty(); + + setNull.AlwaysSet.Should().BeNull(); // <-- this is why I use both the default and set null ruleset + setNull.Value.Should().BeNull(); + + setNullAndDefault.AlwaysSet.Should().NotBeEmpty(); + setNullAndDefault.Value.Should().BeNull(); + } + + public class StringOverride : AutoFakerOverride + { + public override void Generate(AutoFakerOverrideContext context) + { + context.Instance = BuildStringWithPrefix(context.GenerateName); + } + + public static string BuildStringWithPrefix(string prefix) => + $"{prefix}-{Guid.NewGuid().ToString()}"; + } + + public sealed class ExampleClassFaker : AutoFaker + { + public ExampleClassFaker() + { + Config.Overrides ??= new List(); + Config.Overrides.Add(new StringOverride()); + + RuleSet("setnull", set => set.RuleFor(property => property.Value, () => null)); + } + } + [Fact] public void Generate_TestClassWithAbstractClassParameter_should_generate() { diff --git a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/ProductCode.cs b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/ProductCode.cs index 8294f45..1912aff 100644 --- a/test/Soenneker.Utils.AutoBogus.Tests/Dtos/ProductCode.cs +++ b/test/Soenneker.Utils.AutoBogus.Tests/Dtos/ProductCode.cs @@ -3,4 +3,4 @@ public sealed class ProductCode { public string SerialNumber { get; set; } -} \ No newline at end of file +}