Reflection and Unit Testing

This post is prompted by a couple of things: (1) a limitation in the Moq mocking framework, (2) a look back at a unit test I wrote nearly 3 years ago when I first arrived at my current company. While you can use Moq to create an instance of a concrete class, you can’t set expectations on class members that aren’t virtual. In the case of one of our domain entities, this made it impossible to implement automated tests one of our business rules–at least not without creating real versions of multiple dependencies (and thereby creating an integration test). Or so I (incorrectly) thought.

Our solution architect sent me an unit test example that used reflection to set the non-virtual properties in question so they could be used for testing. While the approach is a bit clunky when compared to the capabilities provided by Moq, it works. Here’s some pseudo-code of an XUnit test that follows his model by using reflection to set a non-virtual property:

[Fact]
public override void RuleIsTriggered()
{
  var sde = new SomeDomainEntity(ClientId, null );
  SetWorkflowStatus(sde, SomeDomainEntityStatus.PendingFirstReview);

  var context = GetBusinessRuleContext(sde);
  Assert.True(RuleUnderTest.When(context.Object));
}

private void SetWorkflowStatus(SomeDomainEntity someDomainEntity, WorkflowStatus workflowStatus)
{
  var workflowStatusProperty = typeof(SomeDomainEntity).GetProperty("WorkflowStatus");
  workflowStatusProperty.SetValue(someDomainEntity, workflowStatus, null);
}

With the code above, if the business rule returned by RuleUnderTest looks at WorkflowStatus to determine whether or not the instance of SomeDomainEntity is valid, the value set via reflection will be what is returned. As an aside, the “context” returned from GetBusinessRuleContext is a mock configured to return sde if the business rule looks for it as part of its execution.

After seeing the previous unit test example (and a failing unit test on another branch of code), I was reminded of a unit test I wrote back in 2012 when I was getting up to speed with a new system. Based on the information I was given at the time, our value objects all needed to implement the IEquatable interface. Since we identified value objects with IValueObject (which was just a marker interface), using reflection and a bit of LINQ resulted in a test that would fail if any types implementing IValueObject did not also implement IEquatable. The test class is available here. If you need similar functionality for your own purposes, changing the types reflected on is quite a simple matter.

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.

XUnit: Beyond the Fact Attribute

After using XUnit for unit testing the past couple of years, I finally got a bit tired of the cut-and-paste-and-modify cycle of expanding test coverage for functionality I was building.  I’ve used “row test” functionality in NUnit and MbUnit in the past, but hadn’t gotten around to finding out how to use them in XUnit until quite recently.  The process I followed was relatively short: (1) Add the xunit.extensions dependency to my existing test assembly, (2) take a test that class that contained significant duplication and re-factor it to leverage one of the row testing attributes available.

In my case, the area I picked that would benefit from row testing was workflow testing.  We implement our workflows as state machines with transition tables that define a starting state, an ending state, and the event that triggers the state change.  I’d previously tested these workflows with one unit test per transition, with those three attributes (start state, end state, event) being the only thing different between them.  This meant a single test  that took these attributes as parameters should be sufficient to test transitions, and that the row testing attribute(s) would contain the actual values.

The Theory attribute supports a number of different data sources, including inline data, Excel data, and SQL Server data.  I started with inline data believing it would be the simplest.  But I wasn’t able to get that to work because the InlineData attribute of Theory only appears to support primitives (int, bool, string, etc).  Our workflow events and statuses are classes with attributes that are static and read-only.  From there, I moved on to try the PropertyData attribute.  This attribute takes one string argument that needs to match the name of a property added to the test class that returns a collection of object arrays with one set of test parameters per entry.

Following that approach worked much better.  The results display pretty nicely in ReSharper as well:

XUnitTheoryTestResultReSharper

I’m still working on a code example of this to make available on GitHub, but here are a few links I found useful in getting up to speed with the additional capabilities of XUnit: