NUnit Support for AutoFixture

For a more general introduction to AutoFixture, see my previous post.

For a long time it has been an xUnit exclusive to utilize AutoData in your test suites. The extensibility model of NUnit, made the migration to NUnit cumbersome, to say the least. Recently, Gert Jansen van Rensburg, made the first serious attempt to solve this. Having followed his battles on GitHub, he released the first version of the AutoFixture.NUnit2 NuGet package. 

Although installation and setup is not at smooth as with xUnit, the power of this extension is without question. This post provides a short setup guide on how to install and configure this to work on both local dev machines as well as on TeamCity. The challenge with the extensibility model of NUnit is the distribution of the Addin, the actual plugin or extension to NUnit. This .dll has to be present in the bin\addins folder of NUnit. This is not preferable in a larger multi dev environment, therefore an alternative approach is proposed.

Installation

  1. Go to your NuGet Package Manager, and Install-Package AutoFixture.NUnit2
    • If you have any previous version of AutoFixture installed it will be updated to the latest.
  2. And Install-Package NUnit.Runners
  3. Make a manual reference to tools\lib\nunit.core.interfaces.dll, which resides in your packages folder under NUnit.Runners.
  4. The installation of the AutoFixture.NUnit2 package has inserted this line in your AssemblyInfo.cs-file: [assembly: NUnit.Framework.RequiredAddinPloeh.AutoFixture.NUnit2.Addins.Constants.AutoDataExtension)]
    • Remove this for now.

Now everything is installed and ready to go, except that we need to add the NUnit Addin to the test assembly. I know this is cumbersome, and a bitter pill to swallow. As mentioned above, copying the Ploeh.AutoFixture.NUnit2.Addins.dll-file from the packages folder to your unit test runners bin\addins folder:

 

As proposed here, I could also create a new class, which would inherit the Addin, and add this to the test assembly, but in my test setup I found a better spot.

Setup

Usually I setup my test fixtures using a base class, which among other things holds my AutoFixture configurations, a common setup could look like this:

  1. public class TestBase
  2. {
  3.     protected IFixture Fixture;
  4.     protected GuardClauseAssertion GuardClauseAssertion;
  5.     protected WritablePropertyAssertion WritablePropertyAssertion;
  6.  
  7.     protected void Setup()
  8.     {
  9.         Fixture = new Fixture().Customize(new AutoMoqCustomization());
  10.  
  11.         GuardClauseAssertion = new GuardClauseAssertion(Fixture);
  12.         WritablePropertyAssertion = new WritablePropertyAssertion(Fixture);
  13.     }
  14. }

 

Now this also makes it a perfect spot for my NUnit Addin class, which I’ll include by inheritance:

  1. using NUnit.Core.Extensibility;
  2. [NUnitAddin]
  3. public class TestBase : Ploeh.AutoFixture.NUnit2.Addins.Addin
  4. {
  5.     protected IFixture Fixture;
  6.     protected GuardClauseAssertion GuardClauseAssertion;
  7.     protected WritablePropertyAssertion WritablePropertyAssertion;
  8.  
  9.     protected void Setup()
  10.     {
  11.         Fixture = new Fixture().Customize(new AutoMoqCustomization());
  12.  
  13.         GuardClauseAssertion = new GuardClauseAssertion(Fixture);
  14.         WritablePropertyAssertion = new WritablePropertyAssertion(Fixture);
  15.     }
  16. }

 

So adding the NUnitAddin attribute and inheriting the Ploeh.AutoFixture.NUnit2.Addins.Addin class, I don’t have to copy the addin .dll to the approriate bin\addins folder. Please note the using statement. This way it is by far easier to setup and distribute in the large developer environment. Since also works with TeamCity, otherwise you would have to setup your NUnit Test Launcher on TeamCity to locate the addin, not advisable and a poorly documented approach.

Usage

With all these efforts behind us, we can now easily auto-generate test data via parameters, such as this:

  1. [Test, AutoData]
  2. public void WhateverTestName(int foo, string baa)
  3. {
  4.     // Arrange
  5.  
  6.     // Act
  7.  
  8.     // Assert
  9. }

 

In this test case foo and baa will be assigned auto-generate values by AutoFixture. Now there is much more in the box. So far, the NUnit TestCase attribute have had a rather sparse set of allowed types, such as ints, strings, bool, etc. With AutoData it is now possible auto-generate types as decimal, and even complex types:

  1. [Test, AutoData]
  2. public void WhateverTestName(decimal foo, MyClass sut)
  3. {
  4.     // Arrange
  5.  
  6.     // Act
  7.  
  8.     // Assert
  9. }

 

This is all great and awesome, but wait there is some minors that also might come in handy.

You might have some test scenarios where you would still like to supply your own test data. This will work great along AutoData:

  1. [Test, AutoData]
  2. [TestCase(5, "Some String")]
  3. public void WhateverTestName(int foo, string baa)
  4. {
  5.     // Arrange
  6.  
  7.     // Act
  8.  
  9.     // Assert
  10. }

 

This will generate two test cases, the first one with auto-generated test data from AutoFixture, and the second one with the test data from the TestCase attribute. Note, that the types must be allowed by the TestCase attribute.

Lets consider a more advanced scenario. I have previously described how to use AutoFixture as an auto-mocking container. This is how we would auto-generate and freeze our dependencies using AutoData:

  1. [Test, AutoData]
  2. public void WhateverTestName([Frozen]Mock<IService1> service1Mock,
  3.     [Frozen]Mock<IService2> service2Mock,
  4.     MyClass sut)
  5. {
  6.     // Arrange
  7.  
  8.     // Act
  9.  
  10.     // Assert
  11. }

 

In this test case we let AutoFixture freeze the dependencies that I would like to setup expectations for, and AutoFixture will the inject them during the creation of the MyClass sut.

These are some of the great new possibilities of the latest extension to AutoFixture, you can probably come up with other awesome scenarios.

Finally, I must send all credits for the extension to Gert Jansen van Rensburg. Read his blog and follow him on Twitter.


comments powered by Disqus