Search code examples
c#.netautofixture

How to add postprocessing step to AutoFixture for an object of a particular type after all it's properties has been populated?


I use AutoFixture in my tests and need to generate an object with a particular rules.

I have an object with a few nested properties that contain objects. Business rules are such that one property in each of the nested objects must have a value that is equal to the value of a property from the root object.

Consider:

public class Root {
  public string Number { get; set; }
  public Nested1 Nested1 { get; set; }
  public Nested2 Nested2 { get; set; }
}

public record Nested1 {
  public string Number { get; init; }
}
public record Nested2 {
  public string Number { get; init; }
}

The following rule must follow:

Root.Number == Root.Nested1.Number == Root.Nested2.Number

Is it possible to customize the generation of the Root object such that Nested1.Number and Nested2.Number properties have the same value as in Root.Number?


Solution

  • You can use Customize method in Fixture class. Here's example customization:

    [Fact]
    public void Test1()
    {
        // Arrange
        var fixture = new Fixture();
    
        fixture.Customize<Root>(composer =>
        {
            var s = "some string";
            return composer.With(x => x.Number, s)
                .With(x => x.Nested1, new Nested1 { Number = s })
                .With(x => x.Nested2, new Nested2 { Number = s });
        });
    
        // Act
        var root = fixture.Create<Root>();
    
        // Assert
        Assert.Equal(root.Number, root.Nested1.Number);
        Assert.Equal(root.Number, root.Nested2.Number);
    }
    

    UPDATE

    We can also implement ICustomization interface:

    public class MyCustomzation : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customize<Root>(composer =>
            {
                var s = "some string";
                return composer.With(x => x.Number, s)
                    .With(x => x.Nested1, new Nested1 { Number = s })
                    .With(x => x.Nested2, new Nested2 { Number = s });
            });
        }
    }
    

    And use it like:

    fixture.Customize(new MyCustomzation());