Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2013, Eleutian Technology
E-mail
I've been writing a lot of tests lately because our code coverage isn't up to where we'd like it. NCover+NCoverExplorer is a pretty awesome and while it does have its quirks it has been incredibly useful. A lot of my adventures in writing tests is creating tons of RhinoMocks so that I can pass them to constructors and that sort of thing. So I got a strange idea, and I'm not sure how I feel about it necessarily and figured I'd propose it to all of you out there and get your thoughts.
Basically, 99% of the time in a services unit test, all the interfaces passed to the service will be mocks, so we end up with lots of functions that look like this:
[SetUp] public void Setup() { _service1 = _mocks.CreateMock<IService1>(); _service2 = _mocks.CreateMock<IService2>(); _service3 = _mocks.CreateMock<IService3>(); _serviceWeAreTesting = new DefaultServiceWeAreTesting(_service1, _service2, _service3); }
If we do this a lot for DefaultServiceWeAreTesting, it's often refactored to a single location. All in all, it can be very repetitive to create all the mocks. So, as an experiment I decided to leverage the power of the IoC container, in our case Windsor, to take care of a lot of the mundane for me. In the end I end up with this code:
[SetUp] public void Setup() { _mocks = new MockRepository(); _container = new AutoMockingContainer(_mocks); _service = _container.Create<DefaultServiceWeAreTesting>(); }
AutoMockingContainer is simply a WindsorContainer with a custom facility and dependency resolver that supplies a RhinoMock for any interface that is resolved. We've also moved the setup code into a base class AutoMockingTests that has the container and mock repository. We can then write code that uses the mocks from the container:
[Test] public void DoWork_Always_AsksOtherServices() { using (_mocks.Unordered()) { _container.Get<Service1>().DoWork(); _container.Get<Service2>().DoWork(); _container.Get<Service3>().DoWork(); } _mocks.ReplayAll(); _service.DoWork(); _mocks.VerifyAll(); }
Of course, you don't have to always do the Get call on the container, you can do that in the Setup and use member variables, etc... the point is, the mocked services are created for us. We can also mark other types so that they aren't tested, and take advantage of the IoC and injection that we use in our application to speed up writing and maintaining tests. The implementation I've uploaded allows you to associate a particular strategy with service dependencies. They are:
So, pros and cons? To get things started:
Pros
Cons
What do you think? So far we really like the idea, or at least think it's interesting. Here are the sources:
Source and Binaries