Three simple Rhino Mocks rules

In previous versions of Rhino Mocks, the Record/Replay model was the only way to create and verify mocks.  You would have an area that set up expectations in a record mode, then the replay mode would verify your expectations.  What was really strange about the Record/Replay model was that it didn’t vibe with the “Setup, Exercise, Verify” unit test pattern.  It looked like you had verifications in the middle of your setup, and your verification was just one line of code, “VerifyAll”.  In addition, you had to decide what kind of test double you wanted when you created it.  Last time I checked, there were at least four choices, and I’ll never get any of them straight on what exactly they did differently.

With the new release of Rhino Mocks 3.5, which RTM’d today, the new Arrange, Act, Assert syntax makes it dirt simple to create test doubles for our unit tests.  In fact, I only really abide by three rules for 99.99% of the mocking cases I run into.  All I need to do is abide by three rules:

  1. Use the static MockRepository.GenerateMock method.  Don’t use an instance of a MockRepository, and don’t use the GenerateStub method.
  2. If the mocked instance method returns a value, use the Stub method to set up a result for that value.  This is an indirect input.
  3. If the mocked instance method does not return a value (void), use the AssertWasCalled/AssertWasNotCalled methods.  This is an indirect output.

That’s it.  I rarely, almost never, assert a method was called on a method that returns a value.  The assumption is that indirect inputs should be used to alter the control flow in the application, or to be observed later in indirect or direct outputs.  When I started using Rhino Mocks, I set expectations on every single method call.  This led to brittle tests, where the body of the test matched almost exactly the implementation.  It was ridiculous.

Here’s an example of snippet of code we want to test (yes it was test-driven the first time I wrote it):

public class OrderProcessor
{
    private readonly ISmtpClient _client;
    private readonly IOrderSpec _spec;

    public OrderProcessor(ISmtpClient client, IOrderSpec spec)
    {
        _client = client;
        _spec = spec;
    }

    public void PlaceOrder(Order order)
    {
        if (_spec.IsMatch(order))
        {
            string body = "Huge frickin' order alert!!!rnOrder #:" + order.OrderNumber;

            MailMessage message =
                new MailMessage("sender@email.com", "salesdude@email.com",
                                "Order processed", body);

            _client.Send(message);
        }

        order.Status = OrderStatus.Submitted;
    }
}

Let’s create a test that ensures that when the order specification is a match, we send a message to the SmtpClient:

[Test]
public void Should_send_an_email_when_the_order_spec_matches()
{
    // Arrange
    var client = MockRepository.GenerateMock<ISmtpClient>();
    var spec = MockRepository.GenerateMock<IOrderSpec>();
    var order = new Order {Status = OrderStatus.New, Total = 500m};

    spec.Stub(x => x.IsMatch(order)).Return(true);

    var orderProcessor = new OrderProcessor(client, spec);

    // Act
    orderProcessor.PlaceOrder(order);

    // Assert
    client.AssertWasCalled(x => x.Send(null), opt => opt.IgnoreArguments());
    order.Status.ShouldEqual(OrderStatus.Submitted);
}

I set up the IOrderSpec to return true for IsMatch.  After exercising the OrderProcessor, I ensure that the Send method was called, ignoring any arguments set.  I could have asserted individual parameters, but that’s beyond the scope of this discussion.  What I don’t assert is that the IsMatch method was called.  I don’t care.  If the IsMatch method isn’t called, the Send method won’t be called.  I’ll have more tests to cover the other situations, which will cover all my behavioral specifications I want on the OrderProcessor.

I should also note that I could care less what the GenerateMock method was named.  It could be called GenerateFloogle for all I care, all I’m interested in is how I use the Floogle.  Or Test Double, it doesn’t matter.  I just want a test double, I’ll decide how to use it.  The nice thing about the Rhino Mocks AAA syntax is that I can explicitly setup and verify whatever I want, and the test will fail if I don’t.  I don’t stub properties any more, as I don’t really have any interfaces with properties at this point.  Interfaces are for the most part stateless services, so I don’t need any fancy auto-property behavior for stubs.

Sticking with these three rules for the 99% cases ensures I have good dependency interfaces that conform well to the command/query separation, that method should either perform an operation and return void, or query an object and not change anything.  With the new AAA syntax and these rules, I’ve found my tests to be far less brittle, and much more expressive in describing the behavior I’m specifying.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in Rhino Mocks, TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://blogs.lessthandot.com/index.php/DesktopDev/MSTech/vb-net-rhino-mocks-and-the-aaa-syntax-1 chrissie1

    Pingback from LessthanDot – VB.Net: Rhino Mocks and the AAA syntax

  • FrankM

    Could please explain a little bit about why don’t use the GenerateStub method? Thanks.

  • http://victorkornov.ru Victor Kornov

    I’m using Moq not Rhino but… I prefer to obj.VerifyAll() expectations just because that way you know what EXACTLY went wrong. If you do not verify, then you get some NREs. Could be my fault :)

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @FrankM

    It’s just one less item to worry about. Whether the object is a stub or not is a function of how I use it (Stub() and AssertWasCalled()). Always using GenerateMock means I don’t have to care.

    I also find myself very very rarely creating the Stubs with property-like behavior automatically in there. Maybe it’s the designs I’m working with now, but all my interfaces only have methods, not properties.

    @Victor

    I can definitely see the benefits of using VerifyAll(). But having the Expect up top isn’t AAA any more. I’m fine with NRE’s, but that’s just a preference really. Object Mothers can take care of that issue.

  • http://wontsay@discardmail.org none

    What are NREs?

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @none

    Sorry, “NullReferenceExceptions”. Shoulda called that one out…

  • http://www.pabich.eu/blog Pawel Pabich

    I might be wrong but as long as you don’t set expectations you should use MockRepository.GenerateStub instead of MockRepository.GenerateMock. (http://ayende.com/Wiki/Rhino+Mocks+3.5.ashx#Thedifferencebetweenstubsandmocks)

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @Pawel

    Thanks for the heads up! That might change my mind on which one I use all the time. I’d rather _never_ set expectations.

  • Chris

    Don’t you get an exception when Send was called but not set up as an expectation?

    • Anonymous

      Nope – that’s only if you have a “VerifyAllExpectations” call or similar.

  • http://www.hollman-alu.nl Aluminium Kozijnen

    Can anyone tell me about that generatemock method..

  • Pingback: Rhino Mocks | My Blog

  • Badarinath Pennati

    Thanks Jimmy. Off late I have been trying to get a gist of Rhino Mocks and gone through a lot of Blogs. Your post was helpful.

  • Geoffrey Rayback

    Hey you just exactly nailed my biggest issue with mocks in general. I like your approach much better. I agree that setting complex expectations on the mocked class leads to brittle tests. All I want is the return value.