【发布时间】:2016-02-09 03:33:30
【问题描述】:
动机:我发现自己经常写这样的代码......
myMock.Verify(m => m.SomeMethod(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), ..., It.IsAny<int>()), Times.Never());
也就是说,我经常只是想确保一个给定的方法不会被任何参数组合调用。
写出所有这些 It.IsAny() 常量有点痛苦,我想避免它。我的想法是使用反射来自动化这个常见的用例。这是我第一次尝试为我做这件事的方法:
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() });
}
假设我有一个接口public interface IFoo { string MyFoo(int); },然后我会用VerifyNeverCalledWithAnyParameters(mockFoo, "MyFoo"); 调用这个方法。
虽然它可以编译,但它似乎没有“工作”。也就是说,即使我在验证之前调用了mock对象上的方法,验证也会成功。
我不确定如何继续解决这个问题。有人能在我的反射代码中看到问题吗?
我知道关于 SO 的许多其他问题,这些问题涉及验证在各种奇异场景中调用了方法,但我还没有找到任何解决方案,可以像我希望在这里做的那样以通用方式完成它对于这个常见的用例。
【问题讨论】:
-
你愿意使用strict mocks吗?任何对未设置(通过
Setup())严格模拟的方法的调用都将失败。 -
叹息......当这样一个简单的解决方案存在时,在这个反射代码上浪费了这么多时间:(。谢谢你的提示......听起来它会解决这个问题,也是一个很好的选择提高了我的测试的总体质量。请随时将其发布为答案,我会接受...
标签: c# unit-testing generics mocking moq