Mocking concrete classes using Rhino.Mocks
Pretty much all my agile-aware developer life I have been using Rhino.Mocks to mock interfaces. I had never landed myself in a position where I had to mock a concrete class. Being a Design Purist (well , at least when I review designs), I never liked the idea behind mocking concrete classes Consider a concrete class MyAdder, which I would like to mock. It’s a utility class which can get as trivial as it can. Which would return a sum of two integers x & y.
namespace MyMathLibrary
{
public
class
MyAdder
{
public
int Add(int x, int y)
{
return x + y;
}
}
}
The Unit Test for MyAdder, simple unit Test case
namespace MyMathLibrary.UnitTest
{
// I’m writing my usings here.. TY StyleCop ![]()
using NUnit.Framework;
using Rhino.Mocks;
[TestFixture]
public
class
MyAdderTest
{
[Test]
public
void AddTest()
{
MockRepository mockery = new
MockRepository();
MyAdder mockAdder = mockery.StrictMock<MyAdder>();
// use mockery.CreateMock<> for older versions.
// Return int 5 for all calls..
Expect.On(mockAdder).Call(mockAdder.Add(2, 3));
LastCall.IgnoreArguments().Return(5).Repeat.Any();
mockery.ReplayAll();
int sum = mockAdder.Add(1, 3);
int sum2 = mockAdder.Add(4,3);
Assert.AreEqual(5,sum);
Assert.AreEqual(5,sum2);
}
}
}
But the test would fail & the Error would look something like this
System.InvalidOperationException: There is no matching last call on this object.
Are you sure that the last call was a virtual or interface method call?
at Rhino.Mocks.Impl.RecordMockState.GetLastMethodOptions<T>()
at Rhino.Mocks.MockRepository.LastMethodCall<T>(Object mockedInstance)
at Rhino.Mocks.Impl.CreateMethodExpectation.Call<T>(T ignored)
at MyMathLibrary.UnitTest.MyAdderTest.AddTest()
If you still haven’t figured out, the error. This is because, methods which you would mock from the concrete class should be marked with virtual.And unlike Java by default every method is non virtual. This is a drawback of mocking concrete classes & this is something you will have to live with.
Here’s the new MyAdder class with the black magic & voodoo to run the test cases.
namespace MyMathLibrary
{
public
class
MyAdder
{
public
virtual
int Add(int x, int y)
{
return x + y;
}
}
}
Further read – http://codebetter.com/blogs/jeremy.miller/archive/2006/02/20/138730.aspx