動機:我發現自己經常寫這樣的代碼......用於模擬(MOQ庫)來驗證方法泛型方法從來沒有對任何參數組合稱爲
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");
。
雖然它編譯,它似乎並不「工作」。也就是說,即使我在驗證之前調用模擬對象上的方法,驗證也會成功。
我不確定如何解決這個問題。任何人都可以在我的反射代碼中看到問題嗎?
我所知道的對,這樣講驗證方法被稱爲各種異國情調的場景很多其他的問題,但我還沒有找到,做它在一個通用的方式就像我希望做任何解決方案這裏爲這個常見的用例。
你願意用[嚴格模擬考試(https://github.com/Moq/moq4/wiki/Quickstart#customizing-mock-behavior)?任何未經設置的嚴格模擬(通過'Setup()')調用方法都將使測試失敗。 –
嘆息......在這樣的反射代碼上浪費了很多時間,當這樣一個簡單的解決方案存在:(。謝謝你的提示......這聽起來像它會解決這個問題,也是一個很好的改善,我的一般質量測試,隨意發佈它作爲答案,我會接受它... – sammy34