C# – “Short circuiting” void methods with Moq

cmethodsmockingmoqunit testing

my team has made the decision recently to use Moq as our mocking framework for its tremendous flexibility and highly readable syntax. As we're new to it, I'm stumbling on what appears to be simple questions–searches (here, Google, etc.) find plenty of discussions on other nuances of Moq, but not necessarily what I'm after, and the few seemingly related questions have turned into red herrings.

We're testing a class that has an external dependency (Amazon SimpleDb to be precise) but don't want our tests bound to having a live connection out. A particular method:

  • Applies some "business" logic
  • If appropriate, invokes a call out to SDB via a provider we've built, let's call it SaveItem()

I want to unit test this such that we setup the context required and insure that SaveItem() was invoked, but in a manner that SaveItem() really isn't invoked (because A) the provider to SDB is a mock that isn't fully hydrated and will likely bomb and B) I don't want to have to pay for that transaction hundreds and thousands of times).

When dealing with methods that returned a value, this was trivial.

mockDb.Setup(d => d.GiveMeSomething()).Returns("Foo");

In the case that I outline above though, my "SaveItem()" method is void and therefore the option to use Moq's Returns() method isn't available. And while I can setup a callback to verify SaveItem() is invoked, I can't however seem to get it to not actually do anything.

Naive/hopeful, I thought the following would work, but it appears to still invoke the method:

mockDb.Setup(d => d.SaveItem(It.IsAny<object>()));

So the million dollar question: What's the Moq of the following fictitious code?

mockDb.Setup(d => d.SaveItem(It.IsAny<object>())).STOP_RIGHT_HERE();

Best Answer

If the SaveItem() method is virtual or abstract, and you're not setting Callbase = true, then the method should be re-implemented to do nothing by the mock.

You should be able to do:

mockDb.Setup(d => d.SaveItem(It.IsAny<object>())).Verifiable();

...  test here ...

mockDb.Verify();