Aug 5, 2010

Mocking Comparison – Part 11: Multiple Interfaces

Continuing with our comparison of Rhino Mocks, Moq and NSubstitute we have a look at a little used feature in mocking being the ability to generate mocks that implement multiple interfaces.

Why would you do this though? Well, that’s a good question.  Simple example would be when your class under test expects and object to implement interface X and also implement IDisposable.  It doesn’t happen often, but when it does it’s nice to know the facility is there.

What you’ll see in all the examples is that the mock natively implements a main interface and that to do any interactions with the methods of the second interface requires casting of the mock to that interface.

For the purposes of the code we’re going to pretend that the monkeys of our little zoo are self managing, can act as ZooKeepers and can thus look after themselves.  It’s silly, but it shows the syntax.

Rhino Mocks

The thing to note here is that we can’t use GenerateStub here.  We have to use GenerateMock, which then means we don’t get automatically backed properties, so we have to set them up ourselves as well.

[Fact]
public void Rhino_multiple_interfaces()
{
var monkey = MockRepository.GenerateMock<IMonkey, IZooKeeper>();
monkey.Stub(m => m.Name).PropertyBehavior();
((IZooKeeper)monkey).Stub(k=> k.AssignedMonkey).PropertyBehavior();

monkey.Name = "Spike";
((IZooKeeper)monkey).AssignedMonkey = monkey;

Assert.Equal("Spike", ((IZooKeeper)monkey).AssignedMonkey.Name);

Assert.IsAssignableFrom<IMonkey>(monkey);
Assert.IsAssignableFrom<IZooKeeper>(monkey);
}

You can also see that we have to cast monkey to IZooKeeper every time we want to do something on the IZooKeeper interface.  Annoying, but that’s the way it goes.

Moq

The code here is a little different in that we create the mock the normal way, and then add a new interface to it after it’s already created using the .As<T>() method.

Also, when we set up the property behaviour on the IZooKeeper interface we have to go through some ugly casting and the use of Mock.Get() because of the way Moq separates the Mock and mocked object instances.  Blech.

[Fact]
public void Moq_multiple_interfaces()
{
var monkey = new Mock<IMonkey>();
monkey.As<IZooKeeper>();
monkey.SetupProperty(m => m.Name);
Mock.Get((IZooKeeper)monkey.Object).SetupProperty(k => k.AssignedMonkey);

monkey.Object.Name = "Spike";
((IZooKeeper)monkey.Object).AssignedMonkey = monkey.Object;

Assert.Equal("Spike", ((IZooKeeper)monkey.Object).AssignedMonkey.Name);

Assert.IsAssignableFrom<IMonkey>(monkey.Object);
Assert.IsAssignableFrom<IZooKeeper>(monkey.Object);
}

NSubstitute

This code is by far the smallest because we don’t need to set up the property behaviours.  It’s uses the same approach as Rhino to create the mock itself, and still has the issues of needing to cast to the IZooKeeper interface, but apart from that it’s once again nice and clean code.

[Fact]
public void Nsubstitute_multiple_interfaces()
{
var monkey = Substitute.For<IMonkey, IZooKeeper>();

monkey.Name = "Spike";
((IZooKeeper)monkey).AssignedMonkey = monkey;

Assert.Equal("Spike", ((IZooKeeper)monkey).AssignedMonkey.Name);

Assert.IsAssignableFrom<IMonkey>(monkey);
Assert.IsAssignableFrom<IZooKeeper>(monkey);
}

 

The choice of syntax here is again, quite easy to make.  NSubstitute takes it out.

This also represents a conclusion to the posts focusing on Rhino Mocks, Moq and NSubstitute in the mocking comparison series.  I’m not quite done though as I want to show some usage scenarios where those frameworks don’t work and where tools like Microsoft Moles and TypeMock fit in, so stay tuned – we’re not quite done yet! :-)

 

Other posts in this series:

2 comments:

  1. You're doing it wrong with Moq. Don't you know you can keep the references in variables? :P

    Or chain calls for that matter:

    [Fact]
    public void Moq_multiple_interfaces()
    {
    var monkey = new Mock();
    var keeper = monkey.As();
    monkey.SetupProperty(m => m.Name);
    keeper.SetupProperty(k => k.AssignedMonkey);

    monkey.Object.Name = "Spike";
    keeper.Object.AssignedMonkey = monkey.Object;

    Assert.Equal("Spike", keeper.AssignedMonkey.Name);

    Assert.IsAssignableFrom(monkey.Object);
    Assert.IsAssignableFrom(monkey.Object);
    }

    ReplyDelete
  2. @danielkzu Thanks for the Moq tips. Always happy to be shown when I could be doing something in a better way :-)

    ReplyDelete