2013-06-11 61 views
23

有什麼區別我正在使用Moq並希望創建生成器類以創建我的模擬與預設合理的默認值,可以根據需要在測試設置期間被覆蓋。我採取的方法使用擴展方法,其中我傳遞輸入參數值和期望的輸出。在這樣做的過程中,我看到不同的行爲在我看來是語義上等同的代碼:直接在設置中傳遞It.IsAny(),或在設置中間接傳遞It.IsAny()的值。例如:通過It.IsAny <int>()和它的值It.IsAny <int>()對方法設置

public interface IFoo 
{ 
    bool Bar(int value); 
    bool Bar2(int value); 
} 
public class Foo : IFoo 
{ 
    public bool Bar(int value) { return false; } 
    public bool Bar2(int value) { return false; } 
} 

var mock = new Mock<IFoo>(); 
mock.Setup(x => x.Bar(It.IsAny<int>())).Returns(true); 
Assert.IsTrue(mock.Object.Bar(123));     // Succeeds 

var myValue = It.IsAny<int>(); 
mock.Setup(x => x.Bar2(myValue)).Returns(true); 
Assert.IsTrue(mock.Object.Bar2(123));     // Fails 

兩個調用是等價的(對我來說),但調用失敗BAR2斷言。爲什麼是這樣?

回答

33

It.IsAny只允許Moq匹配在Setup構造中使用的方法調用的未來調用。當調用Setup時,Moq只是將方法調用添加到已設置的方法調用的緩存中。請注意,示例中Setup的參數的類型爲Expression<Func<IFoo, bool>>。由於您傳遞的是Expression,因此不會調用實際的方法調用,並且Moq能夠遍歷表達式以確定方法調用的哪些參數是顯式的,哪些參數是It.IsAny參數。它使用此功能來確定運行時將來的方法調用是否與已經建立的方法調用之一相匹配。

爲了讓這個方法Bar可以接受參數It.IsAny<int>(),有必要使It.IsAny<int>()返回一個int(因爲這是Bar參數的類型)。一般而言,退貨類型It.IsAny<T>必須爲T。必須選擇任意值T。最自然的選擇是default(T),它適用於參考類型和值類型。 (詳細瞭解默認關鍵字here)。在你的情況下,這是default(int),這是0

所以,當你真正評估It.IsAny<int>()立即返回的0值。但是,當你在一個Expression使用It.IsAny<int>()(作爲參數傳遞給Setup方法),那麼方法調用的樹形結構保存和起訂量能夠滿足未來的方法調用由Expression封裝的方法調用。

所以,雖然你不能保持It.IsAny<int>()以任何有意義的方式可變,可以保持整個Expression在一個變量:

Expression<Func<IFoo, bool>> myExpr = x => x.Bar2(It.IsAny<int>()); 
mock.Setup(myExpr).Returns(true); 
Assert.IsTrue(mock.Object.Bar2(123)); 

最後,我只是想提醒你,起訂量是開源的。源可用here。我發現擁有該源代碼非常有價值,這樣我可以點擊並瀏覽代碼和單元測試。

+1

非常好的解釋,本。正如你所描述的那樣,我懷疑問題在於表達式評估,而不是It.IsAny的返回值()。我在ILSpy中查看了反射源,並可以看到它。但是無法讓我的腦袋圍繞它如何解決問題。 再次感謝您的解釋。 –

+0

感謝您爲我清理巫術!我試圖說「var anyFooParam = It.IsAny (); var anyBarParam = It.IsAny ();」看看它是否會讓我的測試更具可讀性,例如:.Setup(mock => mock.method(anyFooParam,anyBarParam))。Returns(something!) –

1

It.IsAny<int>()具有返回爲int類型,並返回0,使你的第二個設置等同於:

mock.Setup(x => x.Bar2(0)).Returns(true); 

我沒有檢查MOQ代碼,但我敢肯定,當計算表達式在設置方法中,它考慮到參數實際上是It.IsAny與正常數字。

,如果您直接在輔助方法創建的設置你都關閉好,而不是通過It.IsAny。

相關問題