I have now fully embraced the world of auto mocking and can now see past the illusion of magic and see it for its wire-up cleanliness. I do not want to have to introduce an additional frameworks, I am a lover of NSubstitute and generally use Windsor as my IoC of choice. The following explains how to create an auto mocking test framework using the two however I am sure you can adapt it to other frameworks.
Auto mocking base class
I have taken the approach of using a base class because it is a better fit for how I do my testing but this could easily be done in a self contained component that can be created in a test fixture. Whilst my real implementation does more than I have put here the main functionality is to create a WindsorContainer, register the LazyComponentAutoMocker which is covered later and the actual class under test. There is then an opportunity in the derived class to do some custom wire up by overriding the SetUp method. It then creates an instance of the class under test via Windsor. The derived classes have the ability of getting hold of registered components or registering their own by calling GetDependency or RegisterDependency respectively.
[TestFixture] abstract class AutoMockedTestFixtureBaseClass<TClassUnderTest> { private WindsorContainer mockContainer; [SetUp] public void virtual AutoMockedTestFixtureBaseClassSetup() { SetUpContainer(); SetUp(); ClassUnderTest = mockContainer.Resolve<TClassUnderTest>(); } private void SetUpContainer() { mockContainer = new WindsorContainer(); mockContainer.Register(Component.For<LazyComponentAutoMocker>()); mockContainer.Register(Component.For<TClassUnderTest>()); } protected virtual void SetUp() { } protected TClassUnderTest ClassUnderTest { get; private set; } protected TDependency GetDependency<TDependency>() { return mockContainer.Resolve<TDependency>(); } protected TDependency RegisterDependency<TDependency>(TDependency dependency) { mockContainer.Register(Component.For<TDependency>().Instance(dependency)); return dependency; } protected void RegisterDependency<TService, TDependency>() where TDependency : TService { mockContainer.Register(Component.For<TService>().ImplementedBy<TDependency>()); } }
Lazy component auto mocker
The lazy component auto mocker uses Windsors ILazyComponentLoader interface to create a dependency on demand via NSubstitute.
public class LazyComponentAutoMocker : ILazyComponentLoader { public IRegistration Load(string key, Type service, IDictionary arguments) { return Component.For(service).Instance(Substitute.For(new[] { service }, null)); } }
Putting it together
The following is an example of how we might test a single class with a single dependency.
public interface ISomeDependency { public int SomeValue { get; } } public class SomeClass { public SomeClass(ISomeDependency someDependency) { DependentValue = someDependency.SomeValue; } public int DependentValue { get; private set; } }
We have defined SomeClass with a dependency of ISomeDependency. The class uses a single property from the dependency to wire up its own internal property.
class When_creating_SomeClass_with_a_given_dependency_value : AutoMockedTestFixtureBaseClass<SomeClass> { protected override void SetUp() { GetDependency().SomeValue.Returns(5); } [Test] public void Should_return_value_from_dependency() { ClassUnderTest.DependentValue.Should().Be(5); } }
As you can see the test wire up is very simple, you have a simple setup of the dependency using NSubstitutes extensions and a simple assertion on the class under test. Here I am using FluentAssertions to assert the value.