Saturday, May 17, 2008

Comparing Moq to Rhino Mocks

Rhino Mocks Vs Moq

As a big believer in test driven development, I spent some time today fiddling around with Visual Studio 2008's new unit testing features. Boy is that a nice addition! As much as I have been a fan of testdriven.net, I am now convinced that there is no longer any point in using the plugin.


The Visual Studio integration makes using NUnit obsolete as well. The whole process is nicely and conveniently built into the IDE, and it is a very welcome addition indeed. The tools are infinitely better and nicer: debugging tests is trivial, grouping tests into packages is easy, and managing configuration items is equally easy.

I am also a big believer in mock frameworks. How do you expect to test functions without separating dependencies? I've worked with unit tests that are completely broken and useless because they never abstracted the data they were testing against. What good is a test that needs to be updated every month or so? Without separating dependencies, unit tests turn into gigantic messes when something fails - because you'll end up with 40 failed tests and no clear indication of where the break occurred. A nicely mocked up suit of unit tests makes it clear where something breaks, because instead of having 40 broken tests you'll have 1. It also allows you to forget about external dependencies such as databases, web services, or text files.

The API that I have used extensively, and I think a lot of other people have adopted as well, is
Rhino Mocks. This superior framework is difficult to use at first, but is incredibly powerful. The greatest thing about Rhino Mocks is that it is strongly typed, which means that all of the Visual Studio refactoring tools work with your unit tests. Without this feature, managing giant suits of tests would be infeasible. While wasting time looking through the MSDN's RSS blog today, however, I ran across an entry that pointed me towards a new framework called Moq. So, naturally, I downloaded it and started to fool around with it. It is tough to say right now which one I prefer, since they both have their advantages. The Rhino API is something I am familiar with, and is flexible enough to do whatever you want with it. Moq, on the other hand, has a very 3.5-ish feel to it, since it draws on Linq expressions and makes heavy use of lambda functions.

Let's look at an example that we can compare and contrast


/// <summary>
/// This class has methods that we will use to run some tests on.
/// </summary>

public class TestClass
{

/// <summary>
/// Gets / sets the aggregated class.
/// </summary>

public AggregatedClass AggregatedClass
{
get;
set;
}

/// <summary>
/// Call the aggregated class.
/// </summary>
/// <param name="x"></param>
/// <returns></returns>

public int Halve(int x)
{
return this.AggregatedClass.Halve(x);
}

}

...

/// <summary>
/// A class that is aggregated by another class.
/// </summary>

public class AggregatedClass
{
/// <summary>
/// Divides a number by 2.
/// </summary>
/// <param name="x">The number to divide.</param>
/// <returns>Half of the number inputted.</returns>

public virtual int Halve(int x)
{
return x / 2;
}

}

Using Rhino Mocks, you would mock the AggregatedClass and test TestClass as follows:



/// <summary>
/// Test using Rhino Mocks API.
/// </summary>

[TestMethod]
public void TestHalve1()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
Expect.Call(aggregatedClass.Halve(12)).Return(6);
mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(6, testClass.Halve(12));
mocks.VerifyAll();

}

Here is the Moq equivalent:


/// <summary>
/// Test using Moq API.
/// </summary>

[TestMethod]
public void TestHalve2()
{
var aggregatedClass = new Mock<AggregatedClass>(MockBehavior.Strict);
aggregatedClass.Expect(x => x.Halve(12)).Returns(6);

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass.Object;
Assert.AreEqual<int>(6, testClass.Halve(12));

aggregatedClass.VerifyAll();

}
In practice, both of these API's do the same thing. But there are a few key differences between the two. The first is that Rhino is very 'Mock-Centric', meaning that everything goes through the MockRepository object. All verifications of expectations, recording, etc., go through the MockRepository. Moq, in contrast, allows mocks to be verified individually.
In practice, I doubt this would be the way I would want to go since it is usually necessary to group mock objects into a single sequence of calls that need to be verified in unison. Fortunately, there is a way to do this using the Moq framework:


/// <summary>
/// Test using Moq API.
/// </summary>

[TestMethod]
public void TestHalve2()
{
MockFactory factory = new MockFactory(MockBehavior.Strict);
var aggregatedClass = factory.Create<AggregatedClass>();
aggregatedClass.Expect(x => x.Halve(12)).Returns(6);

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass.Object;
Assert.AreEqual(6, testClass.Halve(12));

factory.VerifyAll();

}
One thing that is unfortunate about this approach is that the behavior parameter is defined in the MockFactory class, and cannot be customized in any other location (it cannot be set via the Create method). The Rhino Mocks API supports a very essential function called PartialMock, which allows calls to go to the default implementation if no expectation is set on them. This means that Moq has an all-or-nothing approach to setting the behavior of the mocks that it creates. Of course, one can get around this by creating a mix of mock objects using a combination of techniques from both of these examples, but it becomes difficult since the global VerifyAll() call won't work for them. Partial mocks are critical when dealing with abstract classes with abstract methods. One really nice thing about Moq, however, is how it allows you to verify arguments. Take an example where I want to test that Halve is called with a positive number. How is that done with Rhino mocks? Here's one way:


private delegate bool CallbackDel(int x);

/// <summary>
/// Test using Rhino Mocks API.
/// </summary>

[TestMethod]
public void TestHalve1()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
Expect.Call(aggregatedClass.Halve(12)).Return(6);

LastCall.Callback((CallbackDel)((int x) =>
{
return x > 0;
}));

mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(6, testClass.Halve(12));
mocks.VerifyAll();

}
A more elegant solution, however, would be to use constraints:


/// <summary>
/// Test using Rhino Mocks API.
/// </summary>

[TestMethod]
public void TestHalve1()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
Expect.Call(aggregatedClass.Halve(12)).IgnoreArguments().Return(6);
LastCall.Constraints(Is.GreaterThan(0));
mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(6, testClass.Halve(6));
mocks.VerifyAll();

}
One nice thing about Moq is that it makes checking arguments a lot easier. Here's an example of how that works:

/// <summary>
/// Test using Moq API.
/// </summary>

[TestMethod]
public void TestHalve2()
{
MockFactory factory = new MockFactory(MockBehavior.Strict);
var aggregatedClass = factory.Create<AggregatedClass>();
aggregatedClass.Expect(x => x.Halve(It.Is<int>(y => y > 0))).Returns(6);

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass.Object;
Assert.AreEqual(6, testClass.Halve(12));

factory.VerifyAll();

}
The great thing about using delegates for value checking is that you can put whatever you want in there. Want to test that y is an even number? Replace

y => y > 0
...with...

y => y % 2 == 0
I think this is a much more sophisticated system than the one used in the Rhino mocks API. Sadly, it appears that there are still a lot of things left to be done. For instance, where are the ordered and unordered calls? MockFactory does not contain them, and there is no way to set a repeating value. For instance, say we want to test the following method:

/// <summary>
/// Quarters a number.
/// </summary>
/// <param name="x"></param>
/// <returns></returns>

public virtual int Quarter(int x)
{
for(int i = 0; i < 10; i++)
{
if(i % 2 == 0)
{
this.AggregatedClass.Foo(x);
this.AggregatedClass.Bar(x);
}
else
{
this.AggregatedClass.Bar(x);
this.AggregatedClass.Foo(x);
}
}

x = this.AggregatedClass.Halve(x);
return this.AggregatedClass.Halve(x);

}
This is easy with Rhino Mocks:

[TestMethod]
public void TestQuarter()
{
MockRepository mocks = new MockRepository();
AggregatedClass aggregatedClass = mocks.CreateMock<AggregatedClass>();

mocks.BackToRecordAll();
using(mocks.Ordered())
{
using(mocks.Unordered())
{
for(int i = 0; i < 10; i++)
{
aggregatedClass.Foo(12);
aggregatedClass.Bar(12);
}
}

Expect.Call(aggregatedClass.Halve(12));
LastCall.IgnoreArguments().Repeat.Any().Return(3);

}
mocks.ReplayAll();

TestClass testClass = new TestClass();
testClass.AggregatedClass = aggregatedClass;
Assert.AreEqual(3, testClass.Quarter(12));
mocks.VerifyAll();

}
Unfortunately, this is currently not possible with the Moq API. In my mind, this is a pretty serious drawback. The reality is that you need these types of order constraints in order to validate your mock calls. Hopefully, that stuff gets added in the future. The point is that there are a number of exciting things going on in the world of unit testing, and it's fun to see these API's improve. We'll see where it all ends up in a few years.

I have inspired this concept by Michael Braude Blog

Happy Coding!!!