AutoFixture Freeze by Mark Seemann

One of the important points of AutoFixture is to hide away all the boring details that you don't care about when you are writing a unit test, but that the compiler seems to insist upon. One of these details is how you create a new instance of your SUT.

Every time you create an instance of your SUT using its constructor, you make it more difficult to refactor that constructor. This is particularly true when it comes to Constructor Injection because you often need to define a Test Double in each unit test, but even for primitive types, it's more maintenance-friendly to use a SUT Factory.

AutoFixture is a SUT Factory, so we can use it to create instances of our SUTs. However, how do we correlate constructor parameters with variables in the test when we will not use the constructor directly?

This is where the Freeze method comes in handy, but let's first examine how to do it with the core API methods CreateAnonymous and Register.

Imagine that we want to write a unit test for a Pizza class that takes a name in its constructor and exposes that name as a property. We can write this test like this:

What's going on here is that we create a new string, and then we subsequently Register this string so that every time the fixture instance is asked to create a string, it will return this particular string. This also means that when we ask AutoFixture to create an instance of Pizza, it will use that string as the constructor parameter.

It turned out that we used this coding idiom so much that we decided to encapsulate it in a convenience method. After some debate we arrived at the name Freeze, because we essentially freeze a single anonymous variable in the fixture, bypassing the default algorithm for creating new instances. Incidentally, this is one of very few methods in AutoFixture that breaks CQS, but although that bugs me a little, the Freeze concept has turned out to be so powerful that I live with it.

As you can see, the test simply verifies that the constructor parameter is echoed by the Name property, and the Freeze method makes this more explicit while we still enjoy the indirection of not invoking the constructor directly.

Comments

DavidS

Hi,

I am trying to understand how, in this particular example, AutoFixture makes the set up impervious to changes in the constructor.

Say that for whatever reason the Pizza constructor takes another parameter e.g.

public Pizza(string name, price decimal)

Then surely, we'd have to update the test given. Am I missing something?

The CreateAnonymous method reflects over the constructor to figure out which arguments are required. If you add a decimal to the constructor, it's just going to pick that up and supply an anonymous value of decimal. No update of the test is required.

Try it out :)

2012-12-06 08:45 UTC

DavidS

Hey Mark,

Thanks for the prompt reply. Now, I think I understand what's going. Effectively, I was not appreciating that the purpose of "Freezing" was to have the string parameter "Name" "frozen" so that the assertion could be made against a known value.

But your explanation has clarified the issue. Thanks very much.

2012-12-06 13:37 UTC

WesM

I'm curious about how to have different customizations for the same type of object. Example:

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.