One of my former colleagues blogged about using AutoFixture as an auto-mocking container the other day, which got me thinking about auto-mocking with Windsor.
Although I’ve never used auto-mocking myself, a few months ago, I answered a question on StackOverflow, hinting at how auto-mocking could be accomplished with Castle Windsor. I didn’t provide any example code though, so this post will show a more complete solution on how auto-mocking can be implemented with Windsor and Rhino Mocks[1. I realize that all the cool kids are using other mocking libraries these days. I’m still using Rhino though, but it should be a fairly trivial task to “port” this solution to another mocking library.].
A lazy component loader to generate the mocks
First, I create a simple ILazyComponentLoader that lazily registers a Rhino Mocks instance when a particular service is requested – like so:
1 2 3 4 5 6 7 |
public class AutoMockingLazyComponentLoader : ILazyComponentLoader { public IRegistration Load(string key, Type service, IDictionary arguments) { return Component.For(service).Instance(MockRepository.GenerateMock(service, new Type[0])); } } |
– real simple. Windsor’s default lifestyle is singleton, which ensures that subsequent calls for the same service will give me the same mock instance.
Test fixture base class
Then I create a test fixture base class, which is supposed to act as exactly that: a fixture for the SUT:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public abstract class AutoMockingFixtureFor<TAppService> { IWindsorContainer container; protected TAppService service; [SetUp] public void SetUp() { container = new WindsorContainer() .Register(Component.For<ILazyComponentLoader>().ImplementedBy<AutoMockingLazyComponentLoader>(), Component.For<TAppService>()); // build sut and inject mocks for all dependencies service = container.Resolve<TAppService>(); DoSetUp(); } protected virtual void DoSetUp() { } [TearDown] public void TearDown() { DoTearDown(); container.Dispose() } protected virtual void DoTearDown() { } protected TDependency Dep<TDependency>() { return container.Resolve<TDependency>(); } protected TMock Mock<TMock>() where TMock : class { return MockRepository.GenerateMock<TMock>(); } } |
As you can see, my SetUp method creates a new WindsorContainer, registering nothing but my AutoMockingLazyComponentLoader and TAppService – the SUT type. It then uses the container to instantiate the SUT, storing it away in a protected instance variable for test cases to work on.
I included DoSetUp and DoTearDown methods for my test fixtures to override in case they need to – but in most cases, they should not be used because of the coupling they introduce between test cases.
Lastly, I have two methods: Dep, which allows me to access an injected service type (short for “dependency”), and Mock which allows me to generate a new mock object in case I need to mock something other than my SUT’s dependencies.
How to write a new test fixture
As a result of this, a test fixture for something called HandleUpdateDisturbanceForecast is reduced to something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[TestFixture] public class TestOfHandleUpdateDisturbanceForecast : AutoMockingFixtureFor<HandleUpdateDisturbanceForecast> { [Test] public void UpdatesDriverWithReceivedObservableForecast() { // Arrange var now = 19.March(1979).At(12.Hours()); var localUnit = new GenericDriver(); Dep<IProvidesSiteToStartUp>().Stub(p => p.GetLocalUnitByAlias("ali")).Return(localUnit); // Act service.Handle(new UpdateDisturbanceForecast { LocalUnitAlias = "ali", DisturbanceForecast = new List<DisturbancePlanEntry> { new DisturbancePlanEntry {Time = now, Disturbance = 2}, } }); // Assert var forecast = localUnit.DisturbanceForecast; Assert.AreEqual(1, forecast.Count); Assert.AreEqual(now, forecast[0].Time); Assert.AreEqual(2, forecast[0].Value); } } |
– which I think looks pretty slick. And yes, this is an actual test case from something we’re building – doesn’t matter what it’s doing, just wanted to show an actual example.
It’s not like I’m saving a huge amount of coding here – I usually only instantiate my SUT in the SetUp method of my test fixtures, but I like how the “fixed style” of AutoMockingFixtureFor encourages application services to follow a pattern that makes for easy IoC and testing. And the fixture is relieved of almost all clutter that does not directly relate to the thing being tested.