Jul 20, 2010

Mocking Comparison – Part 2: Properties

Carrying on with our Rhino Mocks, Moq and NSubstitute comparison, let’s now look at how the various frameworks handle properties on their mock objects.

Rhino Mocks

So in RhinoMocks you have two choices for creating mock objects – using GenerateMock<T>() or GenerateStub<T>().  GenerateMock will create a mock object that tracks calls made to it so that you can assert expectations against which calls were made at the end of your test.  GenerateStub on the other hand creates a stub object, which is to all intents and purposes the same as a mock object just without any of the overhead for tracking which calls were made against it.  In other words you can do asserts to check if a call was made on a mock, but not on a stub.

Why does this matter?  Because properties on mocks and stubs have different default behaviours in RhinoMocks.

For a mock object we have to explicitly indicate if we want a property to have a standard getter/setter applied to it (i.e. just like an autoproperty implementation).  Here’s some code

[Fact]
public void Rhino_properties()
{
var monkey = MockRepository.GenerateMock<IMonkey>();
monkey.Stub(m => m.Name).PropertyBehavior();

monkey.Name = "Spike";
Assert.Equal("Spike", monkey.Name);
}

and the same test with a stub

[Fact]
public void Rhino_properties()
{
var monkey = MockRepository.GenerateStub<IMonkey>();

monkey.Name = "Spike";
Assert.Equal("Spike", monkey.Name);
}

Note that the stubbed object requires none of the property behaviour setup and so it feels more natural.  While some people may prefer to see properties being set up explicitly rather than implicitly I think that if it is a well known behaviour then it’s not going to be a problem that the property behaviour is implicitly provided on the stubbed objects.

Moq

The Moq code is much the same, however as you can see we have to pay the Moq .Object. tax on our calls.

[Fact]
public void Moq_properties()
{
var monkey = new Mock<IMonkey>();
monkey.SetupProperty(m => m.Name);

monkey.Object.Name = "Spike";
Assert.Equal("Spike", monkey.Object.Name);
}

This makes the code feel just a little more verbose and cumbersome than the Rhino and NSubstitute versions.

In fairness, if you want all properties to be automatically set to the standard autoproperty behaviour for a mock object you can use the SetupAllProperties method in Moq as follows:

[Fact]
public void Moq_properties()
{
var monkey = new Mock<IMonkey>();
monkey.SetupAllProperties();

monkey.Object.Name = "Spike";
Assert.Equal("Spike", monkey.Object.Name);
}

NSubstitute

The NSubstitute code shown below is much the same as the Rhino Mocks code when using stubs.  The difference being that NSubstitute doesn’t differentiate between stubs and mocks.

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

monkey.Name = "Spike";
Assert.Equal("Spike", monkey.Name);
}

Overall, Rhino and NSubstitute are on par, however the more expressive mock object creation and reduced confusion over whether to use mocks or stubs in NSubstitute tilts the balance in favour of NSubstitute.

 

Other posts in this series:

2 comments:

  1. You're missing another alternative v4 syntax for properties (and also methods) in Moq:

    [Fact]
    public void Moq_properties()
    {
    var monkey = Mock.Of(m => m.Name == "Spike");

    Assert.Equal("Spike", monkey.Name);
    }

    The Mock.Of translates to "from the universe of mocks, get me one of that matches this behavior".

    There's also a Mocks.Of (plural) to get an enumerable of mocks.

    ReplyDelete
  2. the generic parameter got cut :(

    ReplyDelete