One of the tenets of the Agile Manifesto reads:

At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

The past few days have been one of those opportunities. In part because of the way our workload was structured, but also because of pain.

For a long time we’ve been using stubs to perform unit testing. This works, but comes with a certain level of baggage. That baggage can turn into pain; pain that can grow over time as the project increases in size. Our project has grown sufficiently large enough that the pain has become more acute, and so we started looking at alternatives.

Through Google, I ran across this post from Alex McMahon. Alex was also using stubs, and wondered if a mock framework would be better. He enumerates the benefits of a mocking framework quite well in his post. The point that he made that resonated the most with me was this:

Decoupling of tests – by not using a single hand coded mock we will avoid coupling tests together by sharing a single mock.

When we started unit testing, this was the road we went down as well: hand-coded stubs. We created stub classes with preloaded data for testing, and then we used those across the suite of unit tests. You can probably imagine the pain that sort of coupling eventually caused.

Using stubs for unit testing equates to state-based unit testing. A typical unit test will involve doing something like fetching a stubbed business object or DTO from a stubbed service, manipulating the stubbed object (like adding an item to a list), and then fetching that stubbed object off a stub view, and asserting a value (for instance, a count).

Problems occur whenever the data for a stub class changes; maybe because of some new requirement for a new test case, or because someone needed additional data for a particular test. Every time the stub data changes it can affect other unit tests and test fixtures. You can try and mitigate that by creating different subsets of the same stub classes with different suites of data, but that becomes a lot of work very quickly.

Coupling unit tests to a hard-coded stub is a bad thing. It might not look like it early on, but as your application grows and requirements change, the problem becomes compounded. This coupling makes tests brittle. Brittle tests are the tools of the devil – they erode developer confidence, which is exactly the opposite of what we’re trying to achieve with unit testing.

With that in mind, I decided to take a look at RhinoMocks. I read Oren’s blog every day through my aggregator. His blog is a great window into the mind of a great developer, so I knew RhinoMocks would rock. It’s also free. And from what I heard while at the ALT.NET conference, RhinoMocks was pretty widely adopted (as was TypeMock).

The first thing you have to get past when switching from stubs to a mocking framework is the syntax. It’s just different. But very quickly it starts to read clearly – much more clearly than a stubbed test fixture. Tests become easier to understand and you can figure out the meaning of a unit test much faster when you can read something like this:

Expect.Call(service.GetEmployee(6)).IgnoreArguments().Return(employee);

Other than the new syntax, the biggest change is switching from state-based testing to interaction-based testing. And I have to say, after some time with RhinoMocks I enjoy the interaction-based testing much better.

Take, for instance, the following test. We want to ensure that a service call is made and a list of Department names is fetched and then passed to the view for binding to a drop down list. To achieve this with stubs, we have to have concrete stubs for the Service & View, and we have to assert the object off the View to make sure it reached its destination. More complicated logic might also test the count of a list, or specific data values on the object that the view contains.

[Test]
public void OnViewReady_FetchesDepartmentNamesFromService_AndUpdatesView()
{
   IPayrollService service = new Stubs.PayrollService();
   IDepartmentsView view = new Stubs.DepartmentsView();
   List departmentNames = new List();
   service.DepartmentNamesDTOReturnValue = departmentNames;

   DepartmentsViewPresenter presenter = new DepartmentsViewPresenter(service);
   presenter.View = view;

   presenter.OnViewReady();

   Assert.AreEqual(departmentNames, view.DepartmentNames);
}

This ends up being a very simple test. But as you begin to test more complicated logic, your asserts quickly grow in number and complexity. Frequent assertions include testing to make sure list counts meet some expected value, or specific fields have certain values.

Imagine testing a list’s Count property to ensure a new item created by the user was added to the list. Now imagine a few days later a fellow developer adds a new item to the default stubbed list. All of your unit tests will fail now because the count will be off by one in the stubbed list.

These problems happen because we’re using state-based testing to verify that a method call or an event publication/subscription actually occurred. It is a roundabout way to perform unit testing on classes that don’t need to worry about state. And this is where interaction-based testing shines.

The same test in RhinoMocks looks something like this:

[Test]
public void OnViewReady_FetchesDepartmentNamesFromService_AndUpdatesView()
{
   MockRepository mocks = new MockRepository();
   IPayrollService service = (IPayrollService)mocks.CreateMock(typeof(IPayrollService));
   IDepartmentsView view = (IDepartmentsView)mocks.CreateMock(typeof(IPayrollService));
   List departmentNames = new List();

   DepartmentsViewPresenter presenter = new DepartmentsViewPresenter(service);
   presenter.View = view;

   
   Expect.Call(service.GetAllDepartmentNames()).Return(departmentNames);
   view.DepartmentNames = departmentNames;
   LastCall.On(view);
   

   presenter.OnViewReady();

   mocks.VerifyAll();
}

What’s great about the RhinoMocks version is that it reads like how you think the program logic should execute. I expect GetAllDepartmentNames to be called with no parameters. I expect the list of DepartmentNameDTO’s to be returned when that call is made. I expect the DepartmentNames property to be set on the view. I don’t care what the list of DTO’s looks like, how much data it has, what the list count is or anything else. Only that methods get called and properties get set.

My test is not dependent on any external classes – everything is mocked for my by RhinoMocks. The test is self-contained. Changes to other tests in this test fixture – or any other test fixture for that matter – won’t cause this test to break. It’s not brittle anymore.

The benefits to this become apparent when you start using the mock framework for more complicated tests, because you can eliminate all data that is state-based and just worry about the flow of the logic. Did the right methods get called? In the right order? The right number of times? Did an event get wired up correctly? Did an event get fired? Caught? Did methods that are not supposed to be called get called? Do I even care?

RhinoMocks lets you ask these questions and answer them in a way that is direct and intuitive.

And, of course, for classes where you do still need to do state-based testing, RhinoMocks lets you do that as well.

Overall, I’m extremely pleased we’ve started using RhinoMocks. I’m more pleased that we’ve moved on from state-based unit testing in classes where it’s not necessary. In short: I’m sold.

6 Comments

  1. Ayende Rahien says:

    I think that you got some problems with the last example, looks like some lines are missing.

  2. Chris says:

    To be fair, I wrote those samples as mostly pseudocode – I’m at home on a weekend. It’s not an actual cut-and-paste of a real test. I’ll fix it Monday Oren :)

  3. Alex McMahon says:

    That was weird, randomly researching something completely different I saw my own name on your blog! That must mean I’ve made it as a blogger ;)

    Anywho, Since I wrote the post you referred to I’ve been working with RhinoMocks for a little while, and one thing I’ve found in the transition is that originally I introduced a level of brittleness in my new tests by over-specifying the interaction that should occur. Any call to a dependency I mocked using an expected interaction, even when this was not absolutely necessary from the test’s perspective.

    The lesson I learnt was that where an interaction is required as far as the test is concerned it should be set up as an expectation for the test, where there is currently an arbitrary call this should be mocked but without the expectation (repeat.any or using rhino stubs)

  4. Chris says:

    Alex,

    What we do, to eliminate some of that brittleness, is always use DynamicMocks. Then you’re free to choose Expect.Call or SetupResult.For based on what you feel has to be tested and what you think you can ignore for a given test. So far it has worked really well.

  5. Alex McMahon says:

    me too, I default to DynamicMock nowadays.

  6. Aaron Feng says:

    We also transitioned from using canned stubs to RhinoMocks in the middle of last year. It’s a nice feeling to be able to delete all those stubs from the repository.

    We also started using the mocks.Record() and mocks.Playback() syntax.For example,

    using(mocks.Record()) {
    Expect.Call(service.GetAllDepartmentNames()).Return(departmentNames);
    // …
    }

    using(mocks.Playback()) {
    presenter.OnViewReady();
    }
    // notice no mocks.VerifyAll()

    This syntax nicely groups all the RhinoMocks statements together.

    I’m not a huge fan of “always” using DynamicMock. The reason for using mocking framework is to be able to test the behavior of an object. The behavior is often more important than how the object arrived at the result. The behavior of an object can not be fully tested when using DynamicMock. Perhaps this is another topic.

    You might find this post interesting:

    http://aaronfeng.com/articles/2007/10/08/another-reason-for-rhino-mocks-generic-constraint