2014-01-21 32 views
3

我使用EasyMoq(http://wp7fx.codeplex.com/)作爲在Windows Store應用嘲弄的框架。在爲測試條件下設置代碼,我有一些代碼,看起來像這樣:爲什麼要將一個值提取到'var'變量的變化行爲?

var mock = Easy.Moq.Mock<SomeClass>(); 
mock.Setup(m => m.SomeMethod("an arg", Allow.Any<AnotherClass>())).Returns("a value"); 

此代碼工作正常。對於那些不熟悉EasyMoq的人,Easy.Moq.Mock<...>()實例化一個模擬,並且mock.Setup(m => m.XYZ()).Returns(...)配置模擬在接收到對模擬的XYZ()方法的調用時返回一個值。表達式Allow.Any<T>()表示它應該匹配任何值。通過查看它的源代碼,顯然它只是返回default(T)。細節並不重要。

,因爲這是一個很長的聲明,我決定通過提取Allow.Any<...>()表達成隱變量來打破它,就像這樣:

var mock = Easy.Moq.Mock<SomeClass>(); 
var arg = Allow.Any<AnotherClass>(); 
mock.Setup(m => m.SomeMethod("an arg", arg)).Returns("a value"); 

但是,此代碼調用失敗後由於System.NullReferenceException方法模擬。這可能是EasyMoq中的一個bug,但我的問題是這樣的:

這個重構如何改變代碼的行爲?

+0

我可以告訴你一兩件事,它沒有任何關係'var'。在C#中'var'沒有特別的意義。只有編譯器可以從RHS表達式中推斷出該類型,否則您的代碼將無法編譯。 'var'的使用不會讓你的類型變成動態類型。如果我做'var name =「evan」;''name'編譯爲一個字符串。如果我的RHS表達式不明確,我只會得到一個編譯器錯誤。 – evanmcdonnal

+2

我相信大部分Moq'Setup' /'Return'代碼都需要表達式並且通過它們來構建實際的模擬。可能在更改之後,它不再能夠正確地遍歷表達式樹來構建驗證器。 –

+0

如果'Allow.Any()'返回'default(T)',那麼如果單步執行代碼,'arg'的值/類型是什麼?根據你的描述,我懷疑它會是'null',但是這仍然不能解釋爲什麼它在內聯時工作,而不是當抽取到變量時。 –

回答

2

我願意打賭.Setup簽名涉及表達式......它可能檢查輸入爲表達式並評估它們......並且由於var語句(其中var不重要)評估Allow.Any<T>調用,則表達式解析default(T)代替Allow.Any<T> ...你能向我們展示.Setup簽名?

+0

這看起來是正確的。根據拆解IL,它確實使用表達式來處理'.Setup'語句,所以對此的解釋是合理的,如果'Allow.Any '呼叫已經評估,並放置在一個臨時不能處理它變量。 –

相關問題