Rhino Mocks Examples, with a fix

Jon Kruger created an excellent explanation of Rhino Mocks, using unit tests to demonstrate and illuminate the syntax and capabilities. (Found via @gar3t.) It needs one small correction, which I’d like to write about here so that I can link to and support Jon’s work, and because it gives the opportunity to clarify a subtle distinction between mocks and stubs and verified expectations.

First, go check out Jon’s code, then come back here.

The problem lies in the following test. I can comment out the part that looks like it is satisfying the assertions, yet the test still passes—a false positive.

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
  var stub = MockRepository.GenerateStub<ISampleClass>();
 
  // Here I'm setting up an expectation that a method will be called
  stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);
 
  //Sneaky Sharon comments out the "Act" part of the test:
  //var output = stub.MethodThatReturnsInteger("foo");
  //Assert.AreEqual(5, output);
 
  // ... and now I'm verifying that the method was called
  stub.VerifyAllExpectations();
}

In translation, that test says: Create a fake ISampleClass; set up an expectation that a method will be called; call that method do nothing; verify that your expectations were met (and flag the test as a failure if they weren’t). Shoot. Worse than not having my expectations met is not realizing they’re not being met. Reminds me of my college boyfriend.

There are two things to fix here. The first is that this test is a little solipsistic. If you create a mock, tell the mock to act, and verify things about the mock… all you’re testing are mocks. Instead, you want your tests to exercise real code. The “system under test,” i.e., the class being tested, should be part of your production code. Its dependencies are what get mocked, so that you can verify proper interactions with those dependencies. Let’s fix the solipsism before going on to the second issue.

As originally written, the expectation would be satisfied by the “Act” (as in Arrange-Act-Assert) part of the test. It says, “Call this method. Did I just call this method? Oh, good.” Instead, you want to ensure the system under test correctly interacts with its friends, using Rhino Mocks’ AssertWasCalled and Expect methods. We need a real class that takes the stubbed class and calls a method on the stubbed class, and we’ll write unit tests around the real class.

public class MyRealClass
{
  public void ActOnTheSampleClass(ISampleClass sampleClass)
  {
  }
}

Here’s the re-written test, verifying how my real class interacts with the ISampleClass interface.

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
  var stub = MockRepository.GenerateStub<ISampleClass>();
  var systemUnderTest = new MyRealClass();
 
  // Here I'm setting up an expectation that a method will be called
  stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);
 
  // Tell the system to act (which, if it is working correctly, 
  // will call a method on the ISampleClass.
  systemUnderTest.ActOnTheSampleClass(stub);
 
  // ... and now I'm verifying that the method was called
  stub.VerifyAllExpectations();
}

This test will still pass, despite the fact that my real class does not currently call any methods on the ISampleClass interface. This points to the second issue to fix. In Rhino Mocks, expectations on stubs are not verified; only mocks are verified. If an object is created with GenerateStub instead of GenerateMock, then its VerifyAllExpectations method doesn’t do anything. This is non-obvious because the AssertWasCalled and AssertWasNotCalled methods on a stub will behave the way you want them to.

In Rhino Mocks, a stub can keep track of its interactions and assert that they happened, but it cannot record expectations and verify they were met. A mock can do both these things.

That is how they are implemented in Rhino Mocks. If you were holding firm to the ideas in Fowler’s Mocks Aren’t Stubs article, I think stubs would implement neither VerifyAll nor AssertWasCalled. Semantically, verifying expectations and asserting interactions are synonymous, if you ask me; therefore, stubs shouldn’t do either one.

Back to Jon Kruger’s tests. If we call GenerateMock instead of GenerateStub, the test will fail properly with an ExpectationViolationException.

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
  var stub = MockRepository.GenerateMock<ISampleClass>();
  var systemUnderTest = new MyRealClass();
 
  // Here I'm setting up an expectation that a method will be called
  stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);
 
  // Tell the system to act (which, if it is working correctly, 
  // will call a method on the ISampleClass.
  systemUnderTest.ActOnTheSampleClass(stub);
 
  // ... and now I'm verifying that the method was called
  stub.VerifyAllExpectations();
}

Now that we’re red, let’s get to green. Change the system under test so that it does its job as expected.

public class MyRealClass
{
  public void ActOnTheSampleClass(ISampleClass sampleClass)
  {
    sampleClass.MethodThatReturnsInteger("foo");
  }
}

Wahoo, a passing test that we can rely on.

The two key points from this exercise are:

  1. Describing Rhino Mocks with unit tests is a cool way to explain a topic. Let’s have more executable documentation, eh?
  2. Expectations on stubs aren’t verified, so beware of falsely passing tests.

Related Articles:

About Sharon Cichelli

I am a Headspring Senior Consultant, developing custom enterprise software for our clients and leading training classes on the latest Microsoft technologies. I blog about .NET development, best practices in agile software development, and my nerdy hobbies.
This entry was posted in Rhino Mocks, unit testing. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Thomas Eyde

    Or we can use a mocking framework with a lesser confusing api. My favourite for the moment is Moq. I haven’t used Rhino Mock since its Record / Replay days, and I failed miserably using that pattern.

    I can relate to Stubs aren’t Mocks, but why should the framework care? For me, the test dummy is a stub when I use it as a stub. If I later choose to use it as a mock, then it is a mock.

    We can debate this issue for as long as we want, but the fact remains that the Rhino Mock API is broken: The non-working VerifyAllExpectations()-method should never have been there in the first place.

  • http://kozmic.pl Krzysztof Kozmic

    Thomas

    You can fall prey to this issue with MoQ as easily as with Rhino Mocks.

    [Test]
    public void Moq()
    {
    var mock = new Mock();

    mock.Setup( m => m.GetFoo() ).Returns( 34 );

    //mock.Object.GetFoo();

    mock.Verify();
    }

    public interface IFoo
    {
    int GetFoo();
    }

    This test will pass although it clearly shouldn’t (it does what I told it to, not what I wanted it to do).

    It’s your choice if you like one framework over another but it has nothing to do with the issue at hand.

  • http://jonkruger.com/blog Jon Kruger

    Interesting. I was trying to figure out the differences between GenerateStub() and GenerateMock() and you pointed out one that I missed. I know what the difference is between a stub and a mock (from an academic perspective), but in Rhino Mocks I find that I never use GenerateMock(). Now, I don’t ever use Expect() and VerifyAllExpectations(), I prefer AssertWasCalled() instead, but that’s just my preference (and probably why I never found this problem before).

    Looks like I’ll have to go update my code (unless you want to send me a patch!).

  • http://simpleprogrammer.com John Sonmez

    Good catch. I think the bigger problem is though it not this incidence, but of not making sure that a test can fail. I wrote about this here: http://simpleprogrammer.com/2010/03/05/the-ego-test/

    I call it an “ego test”, because you can always run it and feel good.

    The only way to really prevent these kinds of problems is to make sure you can make a test fail.

  • http://melioratingmonkey.blogspot.com/ MM

    @Krzysztof – But don’t you think that this “shortcoming” is a little bit more acceptable in Moq because there is only one type of fake? In Rhino Mocks, stub and mock are distinct types so why even put the verify methods on stubs? I think the Moq documentation makes it fairly clear that Verify() will only verify expectations marked as Verifiable (then again, maybe the Rhino Mocks docs make it clear that you should not verify stubs).

    John Sonmez hit the nail on the head. The bottom is line is that this is a good reminder that we should always make sure that our tests fail when they are supposed to.

  • Artur Dorochowicz

    Expect, Assert…, Verify… are implemented as extension methods on object. That’s the only way you can make it work in C#.
    So certainly, Rhino Mocks API is not broken.

  • http://www.lostechies.com/members/rssvihla/default.aspx Ryan Svihla

    For the kinds of test I really prefer obj.AssertWasCalled(x=>x.WhateverMethod), Then I can write asserts against specific method calls. Also with this approach I never have to use Expect and I only need Stub for my return values.

    Ayende has examples of the AssertWasCalled approach in many places but here is one:
    http://ayende.com/Blog/archive/2008/05/16/Rhino-Mocks–Arrange-Act-Assert-Syntax.aspx

  • Thomas Eyde

    @Arthur, we can always debate whether an api is broken or not. But extension methods can operate on different types. My argument is that GenerateMock and GenerateStub should return different types. When that’s the case, we can have extension methods which only operates on one of the types.

    @Krzysztof, you are correct. It’s easy to make the same mistake in Moq. I don’t use Verify very often, so I didn’t know. In that respect, I should probably refrain from commenting.

    One can also argue that the Moq api is broken. I don’t know the rationale behind Verifiable(), but from where I am sitting, every method should be so by default. It’s up to me to call Verify() at the end.

  • http://jonkruger.com/blog Jon Kruger

    I updated my original post to fix the problem that you pointed out in this post. Thanks for pointing that out.

    Jon

  • http://www.clear-lines.com/blog Mathias

    Great post; I have struggled with exactly the same issue, and Rhino.Mocks API doesn’t help understand the difference between Mocks and Stubs, because they both support the same methods, and stubs fail silently. Personally, the aha moment for me came when I read Roy Osherove’s “The Art of Unit Testing”, where he states that a test could fail because of a Mock, but never because of a Stub. That doesn’t resolve the somewhat ambiguous API issues, but that helps in determining whether what you need is a Mock or a Stub!

  • Pingback: On Rhino.Mocks VerifyAllExpectations Vs AssertWasCalled | Something to Read on the Train