AutoMocking with Moq

Decided after a bottle of wine the other night that I might have a go at writing an Auto Mocker.  I know of auto mocking containers, but I’m not a big fan of containers in tests.  There’s also some cool auto mocking stuff been done with MSpec, I’m sure there’s more.  But I was actually pleased at how simple it is with Moq…

I’ve been pairing recently, helping guys apply TDD.  It’s been a lot of fun.  One of the guidelines I try and instill is to only construct the thing under test once, say in the Init().  This is part of my emphasis on keeping test code clean and easy to refactor.  When the thing under test gets a new dependency, it’s one place which you need to change.

But when I sat back and watched, I noticed a lot of repetitive code in the initialize method. 

private Mock<IDependency> dependency;
 
private SomethingWithADependency thingToTest;
 
public void InitWithoutAutoMocker()
{
    this.dependency = new Mock<IDependency>();
    this.thingToTest = new SomethingWithADependency(this.dependency.Object);
    this.dependency.Setup(d => d.SomeMethod()).Returns("hello world");
}

Newing up the thing under test, mocking the dependencies, making them fields etc.  So I though auto mocking could reduce that repetitive stuff.  It has the added side affect that when you add a dependency all tests will still compile, they may pass too…  I guess that could be a downside.  But if you’re writing tests as you go, shouldn’t be a problem…

So with an auto mocker, the above repetitive code shrinks to the following repetitive code.

private AutoMock<SomethingWithADependency> autoMockedThingToTest;
 
public void InitWithAutoMocker()
{
    this.autoMockedThingToTest = new AutoMock<SomethingWithADependency>();
    this.autoMockedThingToTest.GetMock<IDependency>().Setup(d => d.SomeMethod()).Returns("hello world");
}

I’ve not had a go at using this in anger yet, I hope it will save me time and provide a common approach.  If it doesn’t, I’ll try something else…  One thing I’m thinking is it may evolve to have a base test class say AutoMockedTest<TThingToMock> then it will just become mock setup code in Init…  But that’ll fall out of use.

So my test:

public class When_auto_mocking
{
    protected static AutoMock<SomethingWithADependency> autoMock;
 
    Because of = () => autoMock = new AutoMock<SomethingWithADependency>();
 
    It should_mock_dependency = () => autoMock.Object.Dependency.ShouldNotBeNull();
}

 

But, I really need to be able to work with the mocks:

public class When_working_with_automocked_type
{
    protected static AutoMock<SomethingWithADependency> autoMock;
 
    Establish context = () => autoMock = new AutoMock<SomethingWithADependency>();
 
    Because of_method_being_invoked = () => autoMock.Object.Dependency.AMethod();
 
    It can_verify_expectations = () => autoMock.GetMock<IDependency>().Verify(d => d.AMethod());
}

And the first version of the AutoMocker (which I’m sure will grow with use if it adds value).  I actually paired with my house mate and did some more, i.e. handling dependencies such as IDependency[] and IEnumerable<IDependency>…  May post that up once it’s clean…

public class AutoMock<T>
    where T : class
{
    private readonly Type typeToMock = typeof(T);
 
    private readonly Dictionary<Type, Mock> mocks = new Dictionary<Type, Mock>();
 
    public AutoMock()
    {
        this.MockDependencies();
    }
 
    private void MockDependencies()
    {
        var constructor = typeToMock.GetConstructors().First();
        var constructorValues = new List<object>();
        foreach (var param in constructor.GetParameters())
        {
            var dependencyType = param.ParameterType;
            var mockInstance = CreateMock(dependencyType);
 
            constructorValues.Add(mockInstance.Object);
 
            mocks.Add(dependencyType, mockInstance);
        }
 
        this.Object = (T)constructor.Invoke(constructorValues.ToArray());
    }
 
    private static Mock CreateMock(Type dependencyType)
    {
        var notSoGenericMock = typeof(Mock<>).MakeGenericType(dependencyType);
        return (Mock)notSoGenericMock.GetConstructor(new Type[0]).Invoke(new object[0]);
    }
 
    public Mock<TDependency> GetMock<TDependency>() where TDependency : class
    {
        return (Mock<TDependency>)mocks[typeof(TDependency)];
    }
 
    public T Object { get; private set; }
}
Advertisements

About Tom Peplow

C# .Net developer based in London and the South Coast
This entry was posted in Uncategorized and tagged , . Bookmark the permalink.

One Response to AutoMocking with Moq

  1. Pingback: Testing with mocks Top Tip – Use fields to help setup tests | pep => lowdown

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s