Separate Stub and Verify != Duplicate code necessarily

Daniel Cazzulino, author of Moq posted a good comment on my last post where I suggested looking into a Mockito like syntax for .NET Mock Frameworks.

On the surface, Mockito’s approach seems good. But if you do the “true” comparison, you’ll see that stub(…) is exactly the same as mock.Expect(…) in Moq.

Then, when you do verify(…), you have to basically repeat the exact same expression you put in stub(…). This might work if you only have a couple calls to verify, but for anything else, it will be a lot of repeated code, I’m afraid.

I thought this too. See my comment here from a month ago. Szczepan made a good point and I’ve thought about it more since then.

When combined with my position on loose vs strict mocks (almost always use loose), I’d say that *most* of the time you are either stubbing or verifying. Meaning, if you’re verifying you don’t need to stub unless of course that method returns something that is critical to the flow of your test, in which case you don’t really need to verify, because the flow would have verified. That’s a mouthful, but does that make sense?

I haven’t used mockito, and I know there are times I use Expect.Call with return values that matter (which would essentially require you to duplicate stub & verify), but maybe that’s a smell? Maybe if you think you need that you can do state based testing or change your API?

Here’s an example Test using Rhino.Mocks:

[Test]
public void SomeMethod_Always_CallsSendMail()
{
  IMailSender sender = mocks.DynamicMock();
  UnderTest underTest = new UnderTest(sender);

  using (mocks.Record())
  {
    Expect.Call(sender.SendMail()).Returns(true);
  }

  underTest.SomeMethod();

  mocks.Verify(sender);
}

And some code this is testing (obviously not test driven, but you get the idea):

public void SomeMethod()
{
  if (!_sender.SendMail())
  {
    throw new Exception("OH NOS");
  }
}

Notice that here we would need to stub and verify separately with Mockito like syntax. This would look something like this:

[Test]
public void SomeMethod_Always_CallsSendMail()
{
  IMailSender sender = mocks.DynamicMock();
  UnderTest underTest = new UnderTest(sender);

  Stub.That(() => sender.SendMail()).Returns(true);

  underTest.SomeMethod();

  Verify.That(() => sender.SendMail()).WasCalled();
}

This may violate DRY, but what if you designed your API differently? Maybe SendMail should throw an exception on failure instead of returning a boolean? This would make the return value unnecessary and remove the need for the Stub call. Clearly you can’t always do this, especially with unwrapped legacy or API code, but it’s something to think about.

Also, I think you shouldn’t be verifying more than one method generally to go along with the one assert/test rule, so a single repeat would not be that horrendous. Heck, you could even do:

[Test]
public void SomeMethod_Always_CallsSendMail()
{
  IMailSender sender = mocks.DynamicMock();
  UnderTest underTest = new UnderTest(sender);

  Stub.That(var sendMail = () => sender.SendMail()).Returns(true);

  underTest.SomeMethod();

  Verify.That(sendMail).WasCalled();
}

I think the syntax would lead to better, more concise tests. But maybe it would just be too annoying? I wouldn’t know until I tried it for a while I guess.

This entry was posted in frameworks, mocking. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Aaron Jensen

    That’s why I chose a SendMail example. Not being able to send a mail can be considered a system failure and is not normal flow. But you’re right, generally you should not be throwing exceptions for normal flow, I was not recommending that and I should have clarified that.

  • http://www.clariusconsulting.net/kzu Daniel Cazzulino

    Proposing to throw exceptions for normal program flow violates the .NET framework design guidelines and is typically a big no-no: http://blogs.msdn.com/kcwalina/archive/2005/03/16/396787.aspx

    “Do not use exceptions for normal flow of control. Except for system failures, there should generally be a way to write code that avoids exceptions being thrown. ”

    See also http://msdn2.microsoft.com/en-us/library/ms229030.aspx