My previous post about AutoFixture's Freeze functionality included this little piece of code that I didn't discuss:

var mapMock = new Mock<IPizzaMap>();
fixture.Register(mapMock.Object);

In case you were wondering, this is Moq interacting with AutoFixture. Here we create a new Test Double and register it with the fixture. This is very similar to AutoFixture's built-in Freeze functionality, with the difference that we register an IPizzaMap instance, which isn't the same as the Mock<IPizzaMap> instance.

It would be nice if we could simply freeze a Test Double emitted by Moq, but unfortunately we can't directly use the Freeze method, since Freeze<Mock<IPizzaMap>>() would freeze a Mock<IPizzaMap>, but not IPizzaMap itself. On the other hand, Freeze<IPizzaMap>() wouldn't work because we haven't told the fixture how to create IPizzaMap instances, but even if we had, we wouldn't have a Mock<IPizzaMap> against which we could call Verify.

On the other hand, it's trivial to write an extension method to Fixture:

public static Mock<T> FreezeMoq<T>(this Fixture fixture)
    where T : class
{
    var td = new Mock<T>();
    fixture.Register(td.Object);
    return td;
}

I chose to call the method FreezeMoq to indicate its affinity with Moq.

We can now rewrite the unit test from the previous post like this:

[TestMethod]
public void AddWillPipeMapCorrectly_FreezeMoq()
{
    // Fixture setup
    var fixture = new Fixture();
 
    var basket = fixture.Freeze<Basket>();
    var mapMock = fixture.FreezeMoq<IPizzaMap>();
 
    var pizza = fixture.CreateAnonymous<PizzaPresenter>();
 
    var sut = fixture.CreateAnonymous<BasketPresenter>();
    // Exercise system
    sut.Add(pizza);
    // Verify outcome
    mapMock.Verify(m => m.Pipe(pizza, basket.Add));
    // Teardown
}

You may think that saving only a single line of code may not be that big a deal, but if you also need to perform Setups on the Mock, or if you have several different Mocks to configure, you may appreciate the encapsulation. I know I sure do.


Comments

I am still not sure which problem is solved by a SUT factory like autofixture.

You mentioned that adding an indirection between the tests and the SUT constructor helps with refactoring. But if I add a dependency to the SUT, I will still have to add calls to "fixture.Register" to fix my tests. And if I remove a dependency, then my tests will still work but the setup code will accumulate unnecessary cruft. It might be preferable to get a compiler error about a constructor argument which no longer exists.

My own approach for minimizing the impact of refactorings on tests is to just store the SUT and mocks as fields of the test class, and create them in the TestInitialize/SetUp method. That way there is only one place were the constructor is called.
2010-03-27 20:24 UTC
Wim, thank you for writing.

Setting up your Test Fixture by populating fields on the test class is a common approach. However, I prefer not to do this, as it binds us very hard to the Testcase Class per Fixture pattern. Although it may make sense in some cases, it requires us to add new test classes every time we need to vary the Test Fixture even the slightest, or we will end up with a General Fixture, which again leads to Obscure Tests.

In my opinion, this leads to an explosion of test classes, and unless you are very disciplined, it becomes very difficult to figure out where to add a new test. This approach generates too much friction.

Even without AutoFixture, a SUT Factory is superior because it's not tied to a single test class, and if desirable, you can vary it with overloads.

The added benefit of AutoFixture is that its heuristic approach lets you concentrate on only the important aspects of a particular test case. Ideally, AutoFixture takes care of everything else by figuring out which values to supply for all those parameters you didn't explicitly supply.

However, I can certainly understand your concern about unnecessary cruft. If we need a long sequence of fixture.Register calls to register dependencies then we certainly only introduce another level of maintainance hell. This leads us into an area I have yet to discuss, but I also use AutoFixture as an auto-mocking container.

This means that I never explicitly setup mocks for all the dependencies needed by a SUT unless I actually need to configure it. AutoFixture will simply analyze the SUT's constructor and ask Moq (or potentially any another dymamic mock) to provide an instance. This approach works really well, but I have yet to blog about it because the AutoFixture API that supports automocking has not yet solidified. However, for hints on how to do this with the current version, see this discussion.
2010-03-28 09:02 UTC
Wes
I think there is a problem with the code sample you provided. I looked at the source code and did a small test.
I think the following is what you meant (or maybe this article i
// does not work
var td = new Mock();
fixture.Register(td.Object);

// should work
fixture.Inject(td.Object);

fixture.Register(() => td.object);
2014-05-14 14:24 UTC

Wes, thank you for writing. You are indeed correct that this particular overload of the Register method no longer exists, and Inject is the correct method to use. See this Stack Overflow answer for more details.

2014-05-15 09:33 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or Google Plus, or somewhere else with a permalink. Ping me with the link, and I may add it as a comment.

Published

Saturday, 27 March 2010 13:27:02 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!