2010-07-17 47 views
107

想象一下這個類起訂量:怎麼到傳遞給嘲笑服務的方法的參數

public class Foo { 

    private Handler _h; 

    public Foo(Handler h) 
    { 
     _h = h; 
    } 

    public void Bar(int i) 
    { 
     _h.AsyncHandle(CalcOn(i)); 
    } 

    private SomeResponse CalcOn(int i) 
    { 
     ...; 
    } 
} 

莫(Q)他媽的處理器Foo中的一個測試,我怎麼就能夠檢查什麼Bar()已經傳遞到_h.AsyncHandle

+0

你的意思是「AsyncHandle」(多餘的「n」)?你可以發佈處理程序的代碼,或者如果它是標準類型,則指定完全限定類型名稱? – TrueWill 2010-07-17 01:23:13

+0

你能展示你的骨架測試來展示你的想法嗎?雖然我明白,從我們這邊來看,很顯然,從我們這邊來看,似乎有人沒有花時間在沒有做出長期推測性答案的情況下提出問題。 – 2010-07-19 10:12:37

+1

既沒有Foo也沒有酒吧()也沒有這樣的東西。這只是一些演示代碼,可以顯示我所處的情況,而不會分散您的具體應用。我得到了答案,我希望得到。 – Jan 2010-07-21 21:07:06

回答

178

可以使用Mock.Callback法:

var mock = new Mock<Handler>(); 
SomeResponse result = null; 
mock.Setup(h => h.AnsyncHandle(It.IsAny<SomeResponse>())) 
    .Callback<SomeResponse>(r => result = r); 

// do your test 
new Foo(mock.Object).Bar(22); 
Assert.NotNull(result); 

如果你只是要檢查的東西在參數傳遞的簡單,你也可以直接做到這一點:

mock.Setup(h => h.AnsyncHandle(It.Is<SomeResponse>(response => response != null))); 
+1

完美,謝謝! – Jan 2010-07-21 21:04:58

+14

一個方面,如果你的函數有多個參數,你需要在通用的'Callback <>()'Moq方法中指定所有的類型。例如,如果你的方法定義了'Handler.AnsyncHandle(string,SomeResponse)',你需要'/ * ... * /。回調(r => result = r);'。我還沒有在很多地方發現這個明確表示,所以我想我會在這裏添加它。 – 2016-08-31 19:29:00

17

Gamlor的答案的作品,但另一種做法(我認爲在測試中更具表現力的一種方法)是...

var mock = new Mock<Handler>(); 
var desiredParam = 47; // this is what you want to be passed to AsyncHandle 
new Foo(mock.Object).Bar(22); 
mock.Verify(h => h.AsyncHandle(desiredParam), Times.Once()); 

驗證功能非常強大,值得花時間去習慣。

+9

如果你只是想檢查一個方法是否被一個已知參數調用,那麼這種方法很好。如果在編寫測試時尚未創建參數(例如,所討論的單元在內部創建參數),則回調使您可以捕獲和詢問此問題,而您的方法則不然。 – Michael 2014-02-25 14:17:01

+0

我需要存儲傳遞的值,因爲我需要驗證傳遞的所有對象的集合。 – MrFox 2016-09-26 12:47:30

1

您可以使用It.Is<TValue>()匹配器。

var mock = new Mock<Handler>(); new Foo(mock.Object).Bar(22); mock.Verify(h => h.AsyncHandle(It.Is<SomeResponse>(r => r != null)));

+0

Typo - 'AnsyncHandle'應該是'AsyncHandle' – 2017-10-31 16:19:30

2

Gamlor的回答爲我工作,但我想我會擴大約翰木匠的評論,因爲我一直在尋找,涉及多個參數的解決方案。我想其他人偶然遇到這個頁面可能會遇到類似的情況。我在Moq documentation中找到了此信息。

我將使用Gamlor的示例,但假設AsyncHandle方法有兩個參數:一個string和一個SomeResponse對象。

var mock = new Mock<Handler>(); 
string stringResult = string.Empty; 
SomeResponse someResponse = null; 
mock.Setup(h => h.AsyncHandle(It.IsAny<string>(), It.IsAny<SomeResponse>())) 
    .Callback<string, SomeResponse>((s, r) => 
    { 
     stringResult = s; 
     someResponse = r; 
    }); 

// do your test 
new Foo(mock.Object).Bar(22); 
Assert.AreEqual("expected string", stringResult); 
Assert.IsNotNull(someResponse); 

基本上你只需要添加另一It.IsAny<>()與適當的類型,添加另一種類型至Callback方法,並改變lambda表達式適當。