In this fourth part of this series (which is a bit delayed due to my travels to MIX 09) I am going to discuss mocking multiple interfaces and doing callbacks in Moq 3. While these are not features that you are going to use very often, they are features that when you need them, it is often in situations where you have no other option.
Before we get to these two features, I want to really quickly touch on a previous feature that we have already looked at. On Twitter a little bit ago, there was a question about confirming that a method was not called on the mock. To check the number of calls:
mockFileWriter.Verify(fw => fw.WriteLine("1001,10.53"), Times.Exactly(1));
We can use the same construct to make sure that the method was never called:
mockFileWriter.Verify(fw => fw.WriteLine("1001,10.53"), Times.Never());
It is essentially the equivalent of saying “Times.Exactly(0)”, but it just looks much nicer, and provides a better error message. I just wanted to clear this up in case anyone else was wondering.
Mocking Multiple Interfaces
So now let’s look at mocking multiple interfaces. As we have already seen, if we want to create a mock of an interface then we can do it like this:
var mockFileWriter = new Mock<IFileWriter>();
But a situation that you can often get in is where a method requires a particular method, but then also expects the class to implement IDisposable. With some mocking frameworks this can be problematic. Thankfully Moq 3 provides us with an easy way to implement this by use of the “As” method on the mock itself. Some frameworks refer to this as a multi-mock:
var mockFileWriter = new Mock<IFileWriter>(); mockFileWriter.As<IDisposable>();
Now that our mock supports two interfaces, how do we create expectations and verifications on this mock? Well, in the call above, the “As” method returns a Mock<IDisposable"> which allows us to do setup and perform verification on it. We could either hold onto this mock, or if we wanted to later perform verification we could just call “As” again, since we can’t add an interface twice:
mockFileWriter.As<IDisposable>().Verify(d => d.Dispose());
Extremely powerful and very easy to work with!
Next we are going to look at callbacks, which are a feature in Moq that it is entirely possible that you’ll never use. They allow you to specify a chunk of code to be executed when a method is called. So, looking again at the “WriteLine” method above, we could record every invocation into a list:
var values = new List<string>(); mockFileWriter.Setup(fw => fw.WriteLine("1001,10.53")).Callback((string value) => values.Add(value));
Or we could ignore the parameter and just increment a count or something:
int count = 0; mockFileWriter.Setup(fw => fw.WriteLine("1001,10.53")).Callback(() => count++);
But since Moq provides functionality in both of these areas for most of what you would want to do, there isn’t really too many different points at which you would need these tools. In fact, if you think you need to use “Callback” you should probably look a little harder to see if Moq can do what you want to do automatically.
We looked at how to guarantee that a method is never called on a mock. Then we saw how to implement multiple interfaces on a single mock and finally how to use callbacks in Moq. I hope that you found this information useful, and hopefully the next entry in this series will be up soon. In that entry we are going to discuss raising exceptions and events from Mocks.
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
When I run this test, count is not incremented in the debugger. What am I missing?
int count = 0;
mockFileWriter.Setup(fw => fw.WriteLine("1001,10.53")).Callback(() => count++);
I may start to sound like a broken record, but I’m missing the value in the mocking of multiple interfaces. Given your example with the filewriter how would you go about testing the IDisposable. Do you need to to make the IFileWriter extend IDisposable? A complete example would be much appreciated. Thanks!
Good, clear and helpful articles for a Moq newbie like me, however could you please alter the css slightly as any long c# code snippets (that are significantly longer than the centre column width) are truncated.
Currently I have to use view source in the browser to see full code snippets – which breaks up the flow of reading the article!
Issue seen using Firefox 3.6.x and IE8.0.x on Win 7 (not tested with other browsers / OS)
Hi Justin, thanks for your this series. I feel much better about moq and xNunit now.
Very good series. You obviously have the gift of being able to effectively teach what you know in a concise and understandable way. Good job!
Callback is great to use for verifying parameter inputs, in a much more efficient and clear manner than Verify. That’s the main use I have for it.
Leave a comment