This discussion has been had many times, by people far more qualified to comment than myself, but nonetheless, here're my thoughts.
The Story So Far...
I've been programming with unit tests for probably a year now, and as I get opportunities to write code from scratch (I do a huge amount of bug fixes and configuration work it seems!) I'm finding I can get more and more value from them.
About 2 months ago I started playing with the Rhino Mocks mocking framework, so that I can test my code without dependencies slowing down my tests or making them brittle, and I was totally blown away at how much easier my tests became. The ability to mock objects without having to actually create the mock, and the ease with which the mock objects can be configured, is pretty astonishing when you first see it!
However last week a colleague of mine turns out to have been playing with another well known mocking framework, Moq, so I figured it would be worth looking at the two side-by-side before I pick one for use in this project.
Rhino Mocks
Of the two, Rhino Mocks seems to be the more capable - it has been around for a while now (since at least 2005, which really IS a while!), there are plenty of resources around for it, including the excellent quick-reference guide over at Oran Dennison's blog (http://orand.blogspot.com/2007/12/rhino-mocks-quick-reference.html), but there are a few pain points:
- There are about a million different ways of doing things - seriously, there are three different syntaxes, which appear to be completely interchangeable, and still have full support in the framework. This can get really confusing, and unless the guide you're reading is bang up to date, you'll not be getting the newest Arrange/Act/Assert synax in there.
- Arguably it's too powerful - there have been some very interesting discussions around whether or not RhinoMocks encourages you to write overly brittle tests, because of how much control you have over the interaction between the code under test and the mock object.
- Development seems to be tailing off - there've been no updates now for over a year, and the last real milestone release was over 2 years ago.
I'm not going to suggest that the following is the neatest example, for example there's something fishy about having to call Replay on the stub, but a Rhino Mocks test looks something like the following.
[Test]
public void GetDeviceList_NormalUsage_ReturnsThreeDevices()
{
// Arrange
string dummyXmlData = GetDummyFhemXml();
ITelnetRepository telnetStub = new MockRepository().Stub();
telnetStub.Stub(x => x.WriteLine("")).IgnoreArguments();
telnetStub.Stub(x => x.Read())
.IgnoreArguments()
.Return(dummyXmlData);
telnetStub.Replay();
// Act
FhemLiveRepository fhemRepository = new FhemLiveRepository(telnetStub);
IList deviceList = fhemRepository.GetDeviceList();
// Assert that all three devices in the XML have been mapped
Assert.AreEqual(deviceList.Count, 3);
}
Moq
So let's take a look at Moq in comparison. It's the newer of the two, having been around since only December 2007, it's got a much leaner and cleaner syntax (which means it's a lot less powerful), and it seems to be flavour of the month - a quick Google Trends search seems to hilghlight this quite clearly. Again there are some pinch points:
- There's a lot missing, for example there doesn't seem to be a disctinction between a mock and a stub.
- There also doesn't seem to be an easy way to get multiple calls to the same method on a stub return different results, (although there is a clean workaround for this involving queues).
The same code above rewritten for Moq looks like:
[Test]
public void GetDeviceList_NormalUsage_ReturnsThreeDevices()
{
// Arrange
string dummyXmlData = GetDummyFhemXml();
Mock<ITelnetRepository> _telnetStub = new Mock<ITelnetRepository>();
telnetStub.Setup(x => x.Read()).Returns(dummyXmlData);
// Act
FhemLiveRepository fhemRepository = new FhemLiveRepository(telnetStub.Object);
IList<Device> deviceList = fhemRepository.GetDeviceList();
// Assert that all three devices in the XML have been mapped
Assert.AreEqual(deviceList.Count, 3);
}
And The Winner Is...
At the moment, based on the speed with which I've been able to get running with Moq vs the investment that Rhino Mocks took to get going, and the fact that the tests in Moq are a lot more concise, I'm going to go for Moq,
In reality the two frameworks do such a similar job, I wouldn't be suprised if there were some tool available that could automatically take a bunch of Rhino Mocks tests or Moq tests and convert them automatically back and forth, if the project ever "outgrows" Moq, migrating across to Rhino Mocks won't be a horrendous job.
Which is lucky, because I've got a whole load of Rhino Mocks tests in other projects that now I'm beginning to think will have to go!