The Builder Pattern is used to construct a complex object. It can looks something like this:
var thingProvider = MockRepository.GenerateStub<IThingProvider>(); thingProvider.Stub(x => ...) IOrderService orderService = (new OrderServiceBuilder()) .WithThingProvider(thingProvider) .Build();
This is a simple example where I want to create an IOrderService with all default (stubbed) dependencies except I want to override the ThingProvider (one of its dependencies) with a stub that I have supplied.
However I have had go and make a OrderServiceBuilder and add a method for each of its dependencies. This is too much effort.
I commonly create builders in my unit tests because it saves me having to supply mocks to the OrderServices constructor for each test. I only override the dependencies that I need to fulfill the test I am writing thereby making my test code DRY.
To make my life easier and my code even more DRY I decided to create a generic builder that will automatically inject stubs for all the dependencies but allow me to replace them if I want to.
The constructor for the (simplified) type under test looks like:
public OrderService(IThingProvider thingProv, ISomeOtherProvider someOtherProv) { _thingProv = thingProv; _someOtherProv = someOtherProv; }
You should only need to replace the dependencies that you require to complete the test that you are conducting:
IThingProvider mockThingProvider = new ConcreteThingProvider(); IOrderService orderService = (new StubBuilder<IOrderService, OrderService>()) .With(mockThingProvider) .Build();
This is the solution that I came to. It uses a internal UnityContainer to resolve the type under test. The stub builder will register all of the types in the constructor with mock instances. I use Rhino Mocks to make the stubs.
public class StubBuilder<TInterface, TImplementation> where TImplementation : TInterface { protected readonly IUnityContainer Container; public StubBuilder() { Container = new UnityContainer(); var typeOfImplementation = typeof(TImplementation); var constructor = typeOfImplementation.GetConstructors().First(); foreach (var parameter in constructor.GetParameters()) { Container.RegisterInstance(parameter.ParameterType, MockRepository.GenerateStub(parameter.ParameterType)); } Container.RegisterType(typeof(TInterface), typeof(TImplementation)); } public TInterface Build() { return Container.Resolve<TInterface>(); } public StubBuilder<TInterface, TImplementation> With<TDependency>(TDependency dependency) { Container.RegisterInstance(typeof(TDependency), dependency); return this; } }
The With method will overwrite the currently registered ‘stub’ instance with an instance of the callers choice.
I will never (or at least not as often) have to create another builder that injects stubs again.
This StubBuilder will cater for most of the times I need to create a builder, however it does have its limitations. Currently it only supports a single constructor and if the object under test has dependencies that cannot be stubbed I will have to revert back to the old method. I am however happy with it for now.