Moq Sequences Revisited

A while back I wrote about mocking successive calls to the same method which returns a sequence of objects. Read that post for more context.

In that post, I had written up an implementation, but quickly was won over by a better extension method implementation from Fredrik Kalseth.

public static class MoqExtensions
{
  public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup, 
    params TResult[] results) where T : class  {
    setup.Returns(new Queue<TResult>(results).Dequeue);
  }
}

As good as this extension method is, I was able to improve on it today during a coding session. I was writing some code where I needed the second call to the same method to throw an exception and realized this extension wouldn’t allow for that.

However, it wasn’t hard to write an overload that allows for that.

public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup,
    params object[] results) where T : class {
  var queue = new Queue(results);
    setup.Returns(() => {
        var result = queue.Dequeue();
        if (result is Exception) {
            throw result as Exception;
        }
        return (TResult)result;
    });
}

So rather than taking a parameter array of TResult, this overload accepts an array of object instances.

Within the method, we create a non generic Queue and then create a lambda that captures that queue in a closure. The lambda is passed to the Returns method so that it’s called every time the mocked method is called, returning the next item in the queue.

Here’s an example of the method in action:

var mock = new Mock<ISomeInterface>();
mock.Setup(r => r.GetNext())
    .ReturnsInOrder(1, 2, new InvalidOperationException());

Console.WriteLine(mock.Object.GetNext());
Console.WriteLine(mock.Object.GetNext());
Console.WriteLine(mock.Object.GetNext()); // Throws InvalidOperationException

In this sample code, I mock an interface so that when its GetNext method is called a third time, it will throw an InvalidOperationException.

I’ve found this to be a helpful and useful extension to Moq and hope you find some use for it if you’re using Moq.

What others have said

Requesting Gravatar... Josh Nov 24, 2010 11:42 AM
# re: Moq Sequences Revisited
It's interesting that this is such a common situation for people. I blogged about this a few months ago, and didn't even realize you had previously written about it until someone left a comment.

Honestly, I like the Queue approach better than what I came up with.

You would think this would have been rolled into the framework by now. Also, watch out for multi-threaded code as you undoubtedly run into "The Collection Was Modified" exception.

Overall though I have been extremely happy with Moq. That is the kind of API design people should strive for.
Requesting Gravatar... Jack Jackson Nov 24, 2010 6:33 PM
# re: Moq Sequences Revisited
Hi Phil / Josh. I like the queue approach too. Is there any reason you're not commenting about MVC3 RC post?
Requesting Gravatar... mberube Nov 24, 2010 9:16 PM
# re: Moq Sequences Revisited
Thanks Phil. Really interesting topic. Keep on the good work !
Requesting Gravatar... Alxandr Nov 25, 2010 2:29 PM
# re: Moq Sequences Revisited
Intresting post. Just thought I'dd point out that I do think you have a typo: "mock.Setup(r => r.GetNext()" should probably be "mock.Setup(r => r.GetNext())"
Requesting Gravatar... haacked Nov 25, 2010 5:13 PM
# re: Moq Sequences Revisited
@Alxandr Thanks for the correction! I fixed the typo.
Comments have been closed on this topic.