XUnit: Beyond the Fact Attribute (Part 2)

One thing I initially missed about NUnit compared to XUnit (besides built-in support for it in tools like TeamCity) is attributes like SetUp and TestFixtureSetUp that enable you to decorate a method with variables that need to be set (or any other logic that needs to run) before each test or before all the tests in a test fixture.  When I first adopted test-driven development as a work practice, I felt it made things easier.  But the authors of NUnit eventually came to a different conclusion about those attributes, and implemented XUnit without those attributes as a result.

Rather than define attributes for per-test and per-fixture setup, the authors of XUnit recommend using a no-arg constructor where you’d use SetUp and IUseFixture where you’d use TestFixtureSetUp or TestFixtureTearDown.  While this took me some time to get used to, leveraging the interface made it easier to handle the external dependencies of code I needed to implement and test.  One technique I’ve adopted to give myself additional flexibility in my test implementations is to add an extension point to the implementation of the SetFixture method

In this example, the extension point is a method named AdditionalFixtureConfiguration.  Calling it inside SetFixture ensures it will be called before each test class derived from UnitTestBase.  Making the method virtual and keeping it free of implementation means that I only need to override it if I need additional pre-test setup for particular test scenarios.  Because we use StructureMap as our IOC container, the equivalent of UnitTestFixture class in my example has a public attribute of type StructureMap.IContainer.  The AdditionalFixtureConfiguration method provides a natural home for any setup code needed to configure additional mappings between interfaces and implementations, set up mocks, and even inject mocks into the container if a concrete implementation isn’t available (or isn’t needed).

While this is the implementation I’ve chosen, there are certainly other ways to accomplish the same thing.  Instead of defining AdditionalFixtureConfiguration in UnitTestBase, I could define it in UnitTestFixture instead and call it in every SetFixture implementation (or not , if that customization wasn’t needed).  I prefer having the abstract class because it makes for simpler actual test code.