Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoFixture Build-Freeze-Create sequence

I just noticed, that whenever I do Freeze on a fixture in-between Build<>()-Create() calls that Freezes do not get applied. Is it intended behavior of AutoFixture or a bug?

To make things clear:

var fixture = new Fixture().Customize(new AutoMoqCustomization())
var builder = fixture.Build<SomeType>();
fixture.Freeze<Mock<ISomeInterface>>().Setup(m => m.SomeProperty).Returns(10);
var sut = builder.Create();
// if SomeType uses ISomeInterface.SomeProperty it will get 0 returned - *incorrect*

this works fine:

var fixture = new Fixture().Customize(new AutoMoqCustomization())
fixture.Freeze<Mock<ISomeInterface>>().Setup(m => m.SomeProperty).Returns(10);
var sut = fixture.Create<SomeType>();
// if SomeType uses ISomeInterface.SomeProperty it will get 10 returned - correct
like image 746
SOReader Avatar asked Apr 16 '26 23:04

SOReader


2 Answers

It will work if you freeze before calling the builder

Freeze-Build-Create sequence

[TestClass]
public class AutoFixtureTests {
    [TestMethod]
    public void _FreezeBuildCreate() {
        //Arrange
        var expected = 10;
        var fixture = new Fixture().Customize(new AutoMoqCustomization());
        fixture.Freeze<Mock<ISomeInterface>>().Setup(m => m.SomeProperty).Returns(expected);
        var builder = fixture.Build<SomeType>();
        var sut = builder.Create();

        //Act
        var actual = sut.GetA();

        //Assert
        Assert.AreEqual(expected, actual);
    }

    public class SomeType {
        private ISomeInterface a;
        public SomeType(ISomeInterface a) {
            this.a = a;
        }
        public int GetA() {
            return a.SomeProperty;
        }
    }

    public interface ISomeInterface {
        int SomeProperty { get; set; }
    }
}

If you look at the definition of the Build method

Customizes the creation algorithm for a single object, effectively turning off all Customizations on the Ploeh.AutoFixture.IFixture.

If build is called before the freeze all customizations after that would not take effect.

like image 200
Nkosi Avatar answered Apr 18 '26 13:04

Nkosi


So this is how I solved this issue by myself. Since I didn't have much choice in choosing where Build-Create are placed, had to use events for this. Oh, and I didn't want to make Create virtual.

Here's some pseudo-code:

public class BaseSutBuilder<TSut> {
    // other weird stuff...

    // somewhere in ctor:
    protected BaseSutBuilder() {
        SutBuilders = _ => {};
    }

    protected Action<ICustomizationComposer<TSut>> SutBuilders { get; }

    public TSut Create() {
        var builder = _fixture.Build<TSut>();
        SutBuilders(builder);
        return builder.Create();
    }
}

public class SomeTypeSutBuilder: BaseSutBuilder<SomeType> {
    public SomeTypeSutBuilder() {
        SutBuilders += c => c.With(.......
        SutBuilders += c => c.With(.......
    }
}
like image 26
SOReader Avatar answered Apr 18 '26 13:04

SOReader



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!