2015-11-08 45 views
2

動機:我發現自己經常寫這樣的代碼......用於模擬(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");

雖然它編譯,它似乎並不「工作」。也就是說,即使我在驗證之前調用模擬對象上的方法,驗證也會成功。

我不確定如何解決這個問題。任何人都可以在我的反射代碼中看到問題嗎?

我所知道的對,這樣講驗證方法被稱爲各種異國情調的場景很多其他的問題,但我還沒有找到,做它在一個通用的方式就像我希望做任何解決方案這裏爲這個常見的用例。

+0

你願意用[嚴格模擬考試(https://github.com/Moq/moq4/wiki/Quickstart#customizing-mock-behavior)?任何未經設置的嚴格模擬(通過'Setup()')調用方法都將使測試失敗。 –

+0

嘆息......在這樣的反射代碼上浪費了很多時間,當這樣一個簡單的解決方案存在:(。謝謝你的提示......這聽起來像它會解決這個問題,也是一個很好的改善,我的一般質量測試,隨意發佈它作爲答案,我會接受它... – sammy34

回答

1

如果你願意使用strict mocks,你可以得到這個行爲是免費的。任何未經設置的嚴格模擬調用方法(通過Setup())都將使測試失敗。

注意there are trade-offs between loose and strict mocks。鬆散模擬的好處是減少了測試設置並減少了脆性測試。嚴格模擬的好處包括更精確地測試您的被測系統及其依賴性,代價是更多的測試設置。

在你的情況,如果你願意住在增加測試設置那麼他們可以準確地提供你正在尋找的行爲。

相關問題