动机:我发现自己经常写这样的代码......
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");
调用此方法。
虽然它编译,但似乎并没有“起作用”。也就是说,即使我在进行验证之前调用模拟对象上的方法,验证也会成功。
我不确定如何解决这个问题。任何人都可以在我的反射代码中看到问题吗?
我知道关于SO的许多其他问题,谈论验证在各种异国情况下调用方法,但我还没有找到任何解决方案,以通用方式执行它,就像我希望在这里做的那样对于这个常见用例。
答案 0 :(得分:1)
如果您愿意使用strict mocks,则可以免费获得此行为。在未设置的严格模拟上调用方法(通过Setup()
)将无法通过测试。
请注意there are trade-offs between loose and strict mocks。松散模拟的好处是减少了测试设置并减少了脆性测试。严格模拟的好处包括更精确地测试您的被测系统及其依赖性,但代价是更多的测试设置。
在您的情况下,如果您愿意使用增加的测试设置,那么他们可以提供您正在寻找的行为。