Fluent Test Subject Builder with Moq

Attending DDD North a couple of weeks ago, I was inspired by Alastair Smith‘s talk on “Refactoring out of Test Hell”, which covered a few things that a development team can do to make unit testing easier, run faster and generally cause less day-to-day pain than they probably should. One of those things was creating test subjects and how you can create and manage all of the dependencies that a test subject might require. I thought I would write a short post on how we tackled this issue ourselves.

At Orchid, we created this idea of a builder class using a fluent syntax in order to create our test subjects. We required something which would create an instance of whatever type you specify. However, generally it needs to be smarter than that – it needed to be able to provide dependencies, and it needed to be able to provide defaults for dependencies that we’re not really interested in for a given test.

This is what we came up with:

  • A TestSubjectBuilder<T>, where T is the subject under test
  • A Bind<U> method which binds a dependency to the builder for creation
  • A Build method which constructs the instance with all the dependencies

The last point is interesting – how does it construct the instance if you’re not guaranteed to provide all the dependencies it needs?

Resolving dependencies

All that is needed here is a little bit of reflection. Given that we have our test subject T, we can use reflection to find a constructor on that type that we can use. The current implementation only works with subjects that have exactly one constructor, as that it all our requirements called for, but could easily be extended to select a constructor intelligently – perhaps the most specific one.

Then, you walk the parameters that the constructor expects, and match them up with the dependencies that were given to it via Bind(). Bind simply takes the dependency and adds it to an internal ServiceContainer, so that they can be looked up when the constructor arguments are being iterated over.

When the builder comes across a parameter that it does not have an instance for, we dynamically create one using Moq. If the parameter type is U, we use reflection to instantiate Moq<U> and pass that into the constructor instead. This way, the test subject can be built with everything it needs, and because you haven’t explicitly told it to bind a parameter, the assumption is that you’re not interested in anything that happens to that dependency.

A couple of examples of usage:

Simple builder – all constructor arguments are mocked.

var testSubject = new TestSubjectBuilder<UserService>().Build();

Login builder – some arguments are mocked

 // Login controller might accept 3 instances as constructor arguments,
// but I'm only interested in IUserService.. 
// The rest will have mocks automatically created by Moq 
// and used on my behalf. 

var serviceMock = new Mock<IUserService>();  
var controller = new TestSubjectBuilder<LoginController>()  
    .Bind<IUserService>(serviceMock.Object)
    .Build();

We had another requirement where we could create test subjects as mocks of themselves, which would enable us to mock other calls to methods on the same subject being tested. Whether this is ethically correct or not depends on who you are, of course. Usage looks like this:

// Also special-cases for creating Mocks 
var userServiceMock = new TestSubjectBuilder<Mock<UserService>>()  
  .Bind<ISomeDependency>(new TestingDependency())
  .Bind<User>(new TestUser { Username = "testuser" })
  .Build(); 

userServiceMock.Setup(s => ....).Returns(...);  

Depending on Moq

Obviously this implementation heavily depends on the use of Moq (install-package Moq) and the main thing to do to make this more generic would be to abstract out the creation of instances that it doesn’t know about. You would be able to plug in any mocking framework as long as it can create an instance of a given type.

The code

The code is available as a Gist, and I’ve included it here for completeness.