Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2009, Eleutian Technology
E-mail
Jacob posted about the AutoMockingContainer several months ago. At that time we didn't really use it, it was just kind of an implementation of an idea. Well, we've finally started using it in some side projects (Resharper.TestDrive for example), and I must say... wow. It is most definitely the way to instantiate your subject under test most of the time. Why?
I've started to use a base class for all my tests. Let's take a look at ReSharper.TestDrive's test base class:
public abstract class AutoMockingTests { private MockRepository _mocks; private AutoMockingContainer _container; protected MockRepository Mocks { get { return _mocks; } } protected AutoMockingContainer Container { get { return _container; } } [SetUp] public void BaseSetup() { _mocks = new MockRepository(); _container = new AutoMockingContainer(_mocks); _container.Initialize(); Setup(); } public abstract void Setup(); public T Create<T>() { return _container.Create<T>(); } public T Mock<T>() where T : class { return _container.Get<T>(); } public void Provide<TService, TImplementation>() { _container.AddComponent(typeof(TImplementation).FullName, typeof(TService), typeof(TImplementation)); } public void Provide<TService>(object instance) { _container.Kernel.AddComponentInstance(instance.GetType().FullName, typeof(TService), instance); } }
So what's a test look like with this base class? Let's borrow Dave's example.
public class SearchPresenterTests : AutoMockingTests { private SearchPresenter _presenter; private SearchResultDTO _fakeResults; public override void Setup() { this._fakeResults = new SearchResultDTO(); this._presenter = Create<SearchPresenter>(); } [Test] public void Can_search_for_customers_by_number_of_orders() { using (_mocks.Record()) { Expect .Call(Mock<ISearchService>().GetCustomersByOrderCount(42)) .Return(this._fakeResults); } using (_mocks.Playback()) { _presenter.SearchByOrderCount(42); } } [Test] public void Search_results_are_displayed_to_the_user() { using (_mocks.Record()) { mockView.SearchResults = _fakeResults; SetupResult .For(Mock<ISearchService>().GetCustomersByOrderCount(42)) .Return(_fakeResults); } using (_mocks.Playback()) { presenter.SearchByOrderCount(42); } } }
Not bad eh? You can do some more complicated things too. Let's say all your presenters take a hub service called PresenterServices. Rather than mocking it and its child services and setting up expectations for each of the children you can just use the real one and do this:
Provide<IPresenterService>(Create<PresenterService>()); this._presenter = Create<SearchPresenter>();
Now you can refer to all your hub's child services with the Mock<T>() method.
Ok, so if you made it this far you probably want to check it out for yourself. Thanks to Ayende, the AMC it is now part of Rhino.Tools so you can check it out (svn co https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk rhino-tools) and build it yourself or just grab the current trunk build with all the dependencies here. Hope Oren doesn't mind me building and linking this... ;)