Motivation: I find myself often writing code like this...
myMock.Verify(m => m.SomeMethod(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), ..., It.IsAny<int>()), Times.Never());
That is, I often just want to make sure that a given method was NEVER called with any parameter combination.
Writing out all these It.IsAny() constants is a bit of a pain and I'd like to avoid it. My idea was to use reflection to automate this common use-case. Here's my first attempt at a method which would do this for me:
public void VerifyNeverCalledWithAnyParameters<T>(Mock<T> mock, string methodName) where T : class
{
// Get the info for the method in which we're interested
var methodInfo = typeof(T).GetMethod(methodName);
// Get the parameter info for that method
var parameters = methodInfo.GetParameters();
// Build up a list of parameter expressions. Each one will be an It.IsAny<K>() constant, where K is the type of the respective parameter
var parameterExpressions = new List<Expression>();
foreach (var parameterInfo in parameters)
{
var parameterType = parameterInfo.ParameterType;
var itIsAnyObject = typeof(It).GetMethod("IsAny").MakeGenericMethod(parameterType).Invoke(null, null);
parameterExpressions.Add(Expression.Constant(itIsAnyObject));
}
// Build up the lambda which represents "m => m.MethodName(It.IsAny<K1>(), It.IsAny<K2>(),...)"
var delegateType = typeof(Action<IFoo>);
var parameter = Expression.Parameter(typeof(IFoo), "f");
var yourExpression = Expression.Lambda(delegateType, Expression.Call(parameter, methodInfo, parameterExpressions), parameter);
// Verify the method call by invoking the verify method on the mock with our expression and asserting Times.Never() to ensure it was never called with any parameters
mock.GetType().GetMethod("Verify", new[] { yourExpression.GetType(), typeof(Times) }).Invoke(mock, new object[] { yourExpression, Times.Never() });
}
Assuming I had an interface public interface IFoo { string MyFoo(int); }
, I would then call this method with VerifyNeverCalledWithAnyParameters(mockFoo, "MyFoo");
.
Although it compiles, it doesn't seem to "work". That is, the verification succeeds even if I call the method on the mock object before I do the verification.
I'm unsure how to proceed solving this. Can anybody see a problem in my reflection code?
I'm aware of many other questions on SO that talk about verifying that methods were called in various exotic scenarios, but I'm yet to find any solution that does it in a generic way like I'm hoping to do here for this common use case.