September 21, 2007

Rhino Mocks: New syntax

I was browsing though the Rhino Mocks documentation when I found there is an entirely new way to setup a test with mocks.

The old way:

[Test]
public void MyOldTest()
{
// Record your expectations here
Expect.Call(myObject.MyProperty).Return(1);

mocks.ReplayAll();

// do your work here
int i = myObject.MyProperty;

// check you values

mocks.VerifyAll();

Assert.AreEqual(1, i);

}

The new way:

[Test]
public void MyNewTest()
{
// Record your expectations here
using ( mocks.Record() )
{
Expect.Call(myObject.MyProperty).Return(1);
}

// do your work here
int i;
using ( mocks.Playback() )
{
i = myObject.MyProperty;
}

// check you values
Assert.AreEqual(1, i);
}

Now, the most obvious thing about the two code examples is that the new way takes more lines of code. But is that really a valid metric? Not always.

The using statements make a nicer differentiation between the setup and the execution. In the old way, the VerifyAll() method was your differentiator. Sorry, but from four feet back, VerifyAll() just looks like another method. The new way, with the 'with' keyword makes for easier transitions from "what we expect to occur" to "Ok, lets do this thing", and "make sure everything worked as planned."

But wait, there is more!

Now for those of you who think you can NEVER have enough ways to do the same thing, and think that anonymous delegates are the GREATEST THING EVER! There is something for you too.

It is the With statement which gives you a fluent interface (which is all the rage on the blogosphere these days). Anyway, it looks like this:

int i;
With.Mocks(mocoks).Expecting( delegate
{
// Record your expectations here
Expect.Call(myObject.MyProperty).Return(1);
})
.Verify(delegate
{
// do your work here
i = myObject.MyProperty;
}
}
// check you values
Assert.AreEqual(1, i);

Now normally I am all in favor of fluent interfaces. SubSonic, LINQ, and Lambda are all great examples of this. But I worry that the fluent style interface is trying too hard in this case.

That said, sometime soon I'll probably see a use for it and it will be wonderful. But until then.

So now you have seen three ways of doing the same thing with one mocking library. That should be enough to keep everyone busy for a while.

2 comments:

Anonymous said...

Fluent interfaces tend to be fuggo when they involve delegates. They're much nicer with lambas.

Anonymous said...

Cool stuff. Thanks for sharing. I'm going to start using mocks.Record() & mocks.Playback(). It's much more readable.