CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo (.com)

Blog moved to www.jeffreypalermo.com

Rhino Mocks are strongly typed. Refactor unit tests with ease - level 200

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:

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:

 

        [Test, Explicit]

        public void ShouldUpdateUserInformationInProviderWithRhinoMocks()

        {

            Rhino.Mocks.MockRepository mocks = new Rhino.Mocks.MockRepository();

 

            MembershipDataSet dataSet = new MembershipDataSet();

            dataSet.Users.AddUsersRow(new Guid(), "lerma", "lerma", "lksd", "",

                 DateTime.Now.ToShortDateString());

 

            IDataSetStore store = (IDataSetStore)mocks.CreateMock(typeof(IDataSetStore));

            Rhino.Mocks.Expect.Call(store.GetDataSet()).Return(dataSet);

            store.SaveDataSet(dataSet);

 

            mocks.ReplayAll();

 

            StructureMap.ObjectFactory.InjectStub(typeof(IDataSetStore), store);

 

            IMembershipProvider provider = (IMembershipProvider)StructureMap.ObjectFactory.GetInstance(

                 typeof(IMembershipProvider));

            Assert.AreEqual(1, dataSet.Users.Count);

 

            MembershipUser user = provider.GetUser("lerma");//call should trigger the GetDataSet() call;

            user.Email = "lerma@address.com";

            provider.UpdateUser(user);//Should call SaveDataSet(...);

 

            user = provider.GetUser("lerma");//DataSet should be cached, so no call.

            Assert.AreEqual("lerma@address.com", user.Email);

 

            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.



Comments

Daren Desjardins said:

For Java, they have Easymock (http://www.easymock.org/). Very similar except you can mock classes as well as interfaces. Mocking classes has the great advantage of not having to make an interface for every little thing.
# January 3, 2006 12:30 PM

Ayende @ Blog said:

Jeffrey Palermo On Rhino Mocks

# January 13, 2007 2:28 PM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication

News

Headspring Systems

View Jeffrey Palermo's profile on LinkedIn

See my new blog at .jeffreypalermo.com