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:
And here it is in use:
Thanks Phil.
Thil
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.
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.