Customizations with AutoFixture
I’m profound advocate for Test-Driven Development (TDD). I don’t regard myself as a TDD expert, but I’m getting more and more used to the TDD “lifecycle”:There are several advantages to adopting this approach and its beyond the scope of this blog post in particular, I will definitely write an entire blog post on TDD at some point.
When I apply the TDD “lifecycle”, I use a number of tools, which support and ease the lifecycle. I mainly use the NUnit test framework, I have spiked in xUnit, but still stick to NUnit as my primary test framework. An indispensable tool when unit testing is a mocking framework, I have used Moq for a couple years, after leaving Rhino Mocks. They are both great dynamic mocking frameworks, and a must. The last, but not least, primary tool in my TDD toolbox is AutoFixture. Its one of my favorite frameworks, and I almost can’t TDD without it. For those of you not familiar with AutoFixture, I’ll give you short intro.
AutoFixture creates dummy data for your unit tests, so it can be a real time saver. A simple string can be created like this:
- var fixture = newFixture();
- var dummyString = fixture.CreateAnonymous<string>();
The result would be a string with a value like this: “a3cb054d-dbb3-4d97-85be-b11e06784f97".
Likewise you can generate integers. You can generate a finite number of strings:
- var fixture = newFixture();
- var dummyString = fixture.CreateMany<string>();
This would create the as many strings as the fixture.RepeatCount is set to, by default it is set to three. You can also modify the count inline:
- var fixture = newFixture();
- var dummyString = fixture.CreateMany<string>(5);
This would create five dummy strings. If you need to add dummy data to a list:
- var fixture = newFixture();
- var strings = newList<string>();
- fixture.AddManyTo(strings, 5);
This would add five dummy strings to the ‘strings’ list. The power of AutoFixture is that it can also generate dummy objects from your complex classes:
- var fixture = newFixture();
- var dummyMyClass = fixture.CreateAnonymous<MyClass>();
So if my complex class had any public properties like strings, these would be assigned a dummy value. Sometimes it might also be great to set a known value for a property:
- var fixture = newFixture();
- var dummyMyClass = fixture.Build<MyClass>().With(myClass => myClass.Name, "Mads");
There are many more nifty stuff that AutoFixture can help you with, but I’m going to drag you all the way around. For the remaining part of this blog post I’ll focus on how to customize the generation of dummy test data.
There are multiple ways to customize how AutoFixture generates its values. A simple approach to customize the string generation:
- var fixture = newFixture();
- var seededString = fixture.Build<string>().FromSeed(s => "foo").CreateAnonymous();
One piece of dummy data that always takes time is lists. As we learned above we can generate a dummy list in AutoFixture like this:
- var fixture = newFixture();
- var dummyList = fixture.CreateAnonymous<List<MyClass>>();
AutoFixture generates the list for you, but the list is empty. We would have preferred a list of MyClass instances, therefore a small customization is needed:
- var fixture = newFixture().Customize(newMultipleCustomization());
- var dummyList = fixture.CreateAnonymous<List<MyClass>>();
Adding an instance of the MultipleCustomization (line 1), would generate a list of 3 MyClass objects, with a dummy Name string. Remember, three is the default number for AutoFixture. Assume that you have a child class inside your parent class:
- publicclassMyParentClass
- {
- publicstring ParentName { get; set; }
- publicMyChildClass Child { get; set; }
- }
- publicclassMyChildClass
- {
- publicstring ChildName { get; set; }
- }
Generating a list of MyParentClass:
- var fixture = newFixture().Customize(newMultipleCustomization());
- var dummyList = fixture.CreateAnonymous<List<MyParentClass>>();
Would give me a list of 3 MyParentClass, with dummy string ParentName and a dummy MyChildClass, with a dummy string ChildName.
One more thing before jumping into handling abstractions, lets assume that we would like to a list of MyChildClass inside MyParentClass (line 4):
- publicclassMyParentClass
- {
- publicstring ParentName { get; set; }
- publicList<MyChildClass> Children { get; set; }
- }
- publicclassMyChildClass
- {
- publicstring ChildName { get; set; }
- }
This gives me a list of 3 MyParentClass where each has a list of three MyChildClass objects. Remember we can change the number of list items by changing the RepeatCount on the Fixture instance. In some scenarios it might be necessary to change only one of the counts. This is done by using the Register method:
- var fixture = newFixture().Customize(newMultipleCustomization());
- fixture.Register(() => fixture.CreateMany<MyChildClass>(5));
- var dummyList = fixture.CreateAnonymous<List<MyParentClass>>();
Now we have a list of three MyParentClass where each has a list of five MyChildClass. This means that every time the fixture needs to generate a list of MyChildClass, it would use the anonymous method in line 2.
So, abstractions. By default you can’t do something like this:
- var fixture = newFixture();
- var dummyAbstraction = fixture.CreateAnonymous<IService1>();
AutoFixture would throw an exception at you. AutoFixture is not able to create an instance of this interface without a constructor. So you can provide a fake instance, all it requires is that it implements the IService1 interface and then register it to the Fixture:
- var fixture = newFixture();
- fixture.Register<IService1>(() => newFakeService());
- var dummyService = fixture.CreateAnonymous<IService1>();
Now AutoFixture is able to create a dummy version of your FakeService.
I’m a big fan of dependency injection and make heavily use of IoC containers. See my previous post on dependency injection and me. Especially constructor injection is used everywhere.
This often forces me to write a lot of mocking data for all my dependencies, which can be a real time killer:
- var fixture = newFixture();
- var sut = newServiceToTest(newMock<IService1>().Object, newMock<IService2>().Object, newMock<IService3>().Object)
This is just a simple example, sometimes there a many more dependencies. The usual approach with Moq is to set expectations like this:
- var fixture = newFixture();
- var mock = newMock<IService2>();
- mock.Setup(service2 => service2.DoStuff()).Returns("foo");
- var sut = newServiceToTest(newMock<IService1>().Object, mock.Object,
- newMock<IService3>().Object);
This approach is completely fine, but it can be a time killer with a lot of “empty” mocks. Therefore I recently discovered that AutoFixture has an extension using Moq. The way it works is that it uses Moq as a fallback mechanism, by relaying request for creating an abstraction to Moq. I can then refactor the above to the following:
- var fixture = newFixture().Customize(newAutoMoqCustomization());
- var mock = _fixture.Freeze<Mock<IService2>>();
- mock.Setup(service2 => service2.DoStuff()).Returns("foo");
- var sut = _fixture.CreateAnonymous<ServiceToTest>();
Cool, right? In line 1, a new customization is added. This extension is part of AutoMoq extension, available via a Nuget. As usual, AutoFixture creates an instance of the ServiceToTest, bet ServiceToTest takes three dependencies through constructor injection. AutoFixture cannot figure out to create instances of these, they are relayed to Moq. Since I need to set expectations on IService2, I can freeze a variable in the AutoFixture framework, and bypass default behavior for creating instances.
This is a great extension to AutoFixture. combining the mocking features of Moq for supporting auto mocking is great. Since Moq was added, a number of other mocking frameworks has been, AutoFakeItEasy, AutoRhinoMocks, and AutoNSubstitute.
Oh, one more thing. Consider the following class:
- publicclassMyParentClass
- {
- publicstring ParentName { get; set; }
- publicList<IMyChildClass> Children { get; set; }
- }
- publicinterfaceIMyChildClass
- {
- }
Okay, I described such class above, the difference is that it is now a list of interfaces. Remember, lists of concrete instances can be created by using the MultipleCustomizations, and interfaces can be created by using the AutoMoqCustomization, so we need to combine the two. This is done by CompositeCustomization:
- var fixture = newFixture().Customize(newCompositeCustomization(newMultipleCustomization(), newAutoMoqCustomization()));
- var dummyClass = _fixture.CreateAnonymous<MyChildClass>();
This customization combines the two, and creates an instance of MyParentClass, with a list of three MyChildClass instances. Sooo, neat.
That’s it for now. Throw a comment at me, and tell me your AutoFixture niftiest.
Tweetcomments powered by Disqus