I completed my first unit test with Rhino Mocks today.
With well-designed code, one can pick apart a section, mock the
interfaces it needs and run/debug/test it in isolation. This is a
huge advantage of a loosely-coupled design. The alternative is a
tightly-coupled design where every class knows about the API of every
other class, and nothing can be run unless _everything_ is
operational. The worst of this is if you have a development
resource like a database or message queue that isn’t operational at the
moment. You can’t run any of your code because three classes
away something depends on it.
The biggest win, in my opinion, for a loosely-coupled design is
testability. If every dependency is hidden behind a custom
interface, those interfaces can be mocked at will, and your code that
uses these interfaces can be run/debugged/tested at will. This is
where mocking frameworks come in.
I currently use NMock in my automated tests. I’ve also used the mocking framework in nunit.mocks.dll that is available with NUnit (by
the way, version 2.2.5 is out). NMock uses expectations as
strings to define how it will simulate an object that you need.
You can read up on NMock here:
- How to use NMock to assist with unit testing – level 300
- Simple dependency injection to get you started with unit testing – level 200
Rhino Mocks serve
the same purpose, but instead of strings to represent the method that
should be called, it uses the actual method. If follows a record
and play pattern, and you don’t use a string while setting up any of
it. This is a huge time-savor. When you want to rename a
method, you don’t have to search for strings that contain that method
name. The compiler will now catch any errors resulting from the
rename, and your refactoring tool will rename all calls to that method
for you. Here’s a sample test for a custom MembershipProvider I was playing with:
public void ShouldUpdateUserInformationInProviderWithRhinoMocks()
Rhino.Mocks.MockRepository mocks = new Rhino.Mocks.MockRepository();
MembershipDataSet dataSet = new MembershipDataSet();
dataSet.Users.AddUsersRow(new Guid(), “lerma”, “lerma”, “lksd”, “”,
IDataSetStore store = (IDataSetStore)mocks.CreateMock(typeof(IDataSetStore));
IMembershipProvider provider = (IMembershipProvider)StructureMap.ObjectFactory.GetInstance(
MembershipUser user = provider.GetUser(“lerma”);//call should trigger the GetDataSet() call;
user.Email = “firstname.lastname@example.org”;
provider.UpdateUser(user);//Should call SaveDataSet(…);
user = provider.GetUser(“lerma”);//DataSet should be cached, so no call.
mocks.VerifyAll();//make sure the interaction with IDataSetStore was correct.
Note one very big difference between Rhino and NMock. When you
first create the mock, you are in record mode, and for void methods, to
set up the expectation, you actually _call_ the method. Rhino
sees that and adds the expectation. For non-void methods, you use
Expect.Call to set up the return value. When you are ready
to run the code under test, you have to switch to play mode using the
ReplayAll() method. And then at the end there is the obvious
VerifyAll() method. Rhino supports Replay and Verify for all
mocked objects at once or one by one.
In this code sample. I’m using StructureMap in my production code to
link dependencies. Here, I tell StructureMap to use the mocked
object instead. Read up on StructureMap here.
So far, I’ve found Rhino Mocks to have every feature that I currently use with NMock plus the strongly-typed expectations.
I’m considering making a switch. For the time being, I’ll
continue to use Rhino for new tests as a longer evaluation. To
get more information on how Rhino Mocks work, read the documentation, which is very good.