The Joy of Moq – Multiple Interfaces

By | August 30, 2010

A few weeks ago I wrote about how my team has been making the switch to Moq over NMock; since then, we really haven’t looked back. Recently I had cause to use a couple of Moq’s features that reinforced the decision to make the switch: partial mocking, and mocking an object that implements multiple interfaces. In this post we’ll be reviewing mocking multiple interfaces.

 

The Class Diagram

Below is the class diagram that represents the mocked (get it) up classes that we’ll be using.

classDiagram

 

The contrived example is just that, contrived. We have two simple interfaces with one method a piece, and one class that implements both of these interfaces. The class diagram doesn’t show the full picture for SomeClass, but the code does.

public class SomeClass 
{
    public static int MultipleInterfaceUser<T>(T x) 
        where T : IFirstInterface, ISecondInterface
    {
        IFirstInterface f = (IFirstInterface)x;
        ISecondInterface s = (ISecondInterface)x;

        return f.SomeMethodOnFirstInterface() + s.SomeMethodOnSecondInterface();
    }
}

 

Note that we’re declaring the constraint on our type parameter for the MultipleInterfaceUser method such that any parameter must implement both of our interfaces, namely IFirstInterface and ISecondInterface. The code then uses both interfaces to return a value.

 

The Mock

Below is the test that exercises this code.

[Test]
public void MultipleInterfaceTest()
{
    Mock<SomeClassImplementingInterfaces> c = 
        new Mock<SomeClassImplementingInterfaces>();

    Mock<IFirstInterface> firstMock = c.As<IFirstInterface>();
    firstMock.Setup(m => m.SomeMethodOnFirstInterface())
        .Returns(2);

    Mock<ISecondInterface> secondMock = firstMock.As<ISecondInterface>();
    secondMock.Setup(m => m.SomeMethodOnSecondInterface())
        .Returns(4);

    int returnValue = 
        SomeClass.MultipleInterfaceUser<SomeClassImplementingInterfaces>(c.Object);

    Assert.That(returnValue, Is.EqualTo(6));
}

 

The secret sauce here is Moq’s “As” keyword. It allows us to build up an object that implements multiple interfaces such that said interfaces are mockable. If we were to try the same thing above with the below code, we would receive an error telling us that Moq can’t override a any of the interface methods.

[Test]
public void MultipleInterfaceTest()
{
    Mock<SomeClassImplementingInterfaces> c = 
        new Mock<SomeClassImplementingInterfaces>();
    c.Setup(m => m.SomeMethodOnFirstInterface()).Returns(2);
    c.Setup(m => m.SomeMethodOnSecondInterface()).Returns(4);

    int returnValue = 
        SomeClass.MultipleInterfaceUser<SomeClassImplementingInterfaces>(c.Object);

    Assert.That(returnValue, Is.EqualTo(6));
}

 

The actual error is pictured below.

mockError

 

Returning to our test, we can see that once we’ve built up our mock SomeClassImplementInterfaces object and setup appropriate expectations, we can pass the resultant object into the MultipleInterfaceUser method and successfully get back the value we expected.