SOReader
SOReader

Reputation: 6047

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

Upvotes: 3

Views: 2425

Answers (2)

SOReader
SOReader

Reputation: 6047

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(.......
    }
}

Upvotes: 1

Nkosi
Nkosi

Reputation: 247531

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.

Upvotes: 2

Related Questions