I have on several occasions wished that I could setup expectations in Moq for subsequent calls to a method. For example, I might want Moq to return one value the first time a method is called, but a different value the second and third times. Phil Haack has a nice way to achieve this, but his implementation only allows you to return a result. What if you need something more advanced? What if you want to return a value on the first call, throw an exception on the second, and return a value again on the third? I ran into exactly this situation while testing out some error-handling logic in a class. Here’s how I achieved it.
public static class MoqExtensions
{
public static IReturnsResult<TMockType> Returns<TMockType, TReturnType>(this IReturns<TMockType, TReturnType> expression, params Func<TReturnType>[] results)
where TMockType : class
{
int nextResult = 0;
return expression.Returns(() => results[nextResult++]());
}
}
This adds a new Returns method you can use with Moq in place of one of the built-in Return methods. It allows you to specify an arbitrary number of Func’s to be executed. Instead of using Moq to return the Func’s directly, it creates a new Func (via a lambda expression) that will iterate over the result Func’s specified. It does this via a closure around the results and the index of the next result. Note that it accepts a ‘params’ array, so calling it still looks (fairly) clean:
[Test]
public void ContinuesWorkingIfErrorEventIsHandled()
{
mResultSet.Setup(r => r.GetNextResult()).Returns((Func<IResult>)(() => { throw new NotImplementedException(); }), () => null);
//Run...
mResultSet.Verify(r => r.GetNextResult(), Times.Exactly(2));
}
That’s all there is to it!
Tags: