Moq'ing Successive Calls to a Method

I just ran into a little problem when using Moq - I wanted to be able to mock up the result of a method call, but return a different result each time the mocked method was called (I'm pulling messages out of an MSMQ within a loop). Anyone who's used Moq will know that you usually mock results with the Setup() method - however, Moq has no built in way of achieving this (that I'm aware of).

To cut a long explanation short, I found a series of articles on Phil Haack's blog addressing (almost) the same issue. Phil's second post adds exception handling to his original example, but I wanted to return a "null", rather than throw an exception. Here's the code from Phil's blog, slightly rehashed to deal with nulls:

    public static class MoqExtensions {
        public static IReturnsResult<T> ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup,
            params object[] results) where T: class {
            var queue = new Queue(results);

            return setup.Returns(() => {
                var result = queue.Dequeue();
                if (result is Exception) {
                    throw result as Exception;
                }
                if (result == null) {
                    return default(TResult);
                }
                return (TResult)result;
            });
        }
    }

And here it is in use:

mockQueue
    .Setup(x => x.GetNextMessage())
    .ReturnsInOrder(new InputMessage(), new InputMessage(), new InputMessage(), null);

Thanks Phil.

Thil

UPDATE 28th Dec 2013


I've just been trying to append a callback to the above method using Moq's fluent notation - but I couldn't, as it returned void. I've modified the example above to return setup.Returns, allowing you to then chain notation as you would normally with Moq.

Popular posts from this blog

Handling uploads with MVC4, JQuery, Plupload and CKEditor

Generating a self-signed SSL certificate for my QNAP NAS

TDD and Unit Testing with Moq