2010-03-05 129 views
20

Rhino Mocks存根和mock只適用於接口而不是具體的類是否正確?我花了很長時間試圖讓這段代碼工作。我沒有想到,存根的pubSubClient總是從類中調用Send方法。該方法有一些依賴關係並拋出異常。犀牛嘲笑存根和嘲笑只適用於接口?

[Test] 
public void Test01() 
{ 
    PubSubMessage psm = new PubSubMessage(); 
    var pubSubClient = MockRepository.GenerateStub<PubSubClient>(); 
    pubSubClient.Stub(x => x.Send(psm)).IgnoreArguments().Return(null); 
    // actual PubSubClient Send method throws exception 
    // the rest of the test is skipped... 
} 

但是,當我提取接口並使用IPubSubClient運行相同的測試時,它似乎按預期工作。

這是否意味着我必須爲每個我想用犀牛模擬/存根的類提取界面?或者我缺少技術或概念上的東西?

UPDATE:OK,我似乎想通了什麼部分我失蹤: 犀牛嘲笑無法攔截到非虛方法電話。所以,我想我要麼使用接口,要麼讓具體類的每個方法都是虛擬的。如果有其他選擇,請糾正我。

回答

23

布賴恩的使用部分嘲笑的答案是不正確的。這不是部分嘲諷。

Jon Erickson的回答大部分是正確的:Rhino Mocks和Moq不能攔截非虛擬調用,也不能攔截靜態方法或屬性。這意味着你不能僞造以下內容:

DateTime.Now; // static property, can't fake static property 
someClass.SomeNonVirtualMethod(); // can't fake non-virtual method 
sealedClass.Foo(); // can't fake anything on sealed classes 
Utilities.SomeStaticMethod(); // can't fake static methods 
someList.Any(); // can't fake extension methods like Linq's .Any() 

TypeMock可以僞造這些,正如喬恩提到的。

應該指出的是,還有一個額外的模擬框架,可以攔截所有的電話:Microsoft Moles framework。它的工作方式與TypeMock相同,它使用.NET Profiler API截取調用。

痣是免費的(現在)。它也是測試版。痣只能與Microsoft Pex tools一起使用。它的API顯然不如TypeMock精緻,優雅的API。

+4

如果你聲明部分模擬不適合某些事情,那麼在你的回答中說出它們的含義會更有幫助。部分模擬僅用於模擬某個類的一部分,這使得它們很方便(並且需要)模擬出一個普通模擬無法處理的抽象類。這允許抽象方法的測試。部分模擬(至少在Rhino中)將嘲笑任何類,並且不限於抽象類,但請注意,是否存在將在返回時調用的實現代碼。 – 2010-09-27 11:28:37

+0

(necro警報):我剛發現你的班級甚至不需要抽象以使方法變爲虛擬!這麼小的事情,但我從來沒有考慮過它:-) – Heliac 2014-10-03 07:24:39

1

部分模擬允許您嘲笑具體類的功能。請參閱:http://www.ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx

+0

恐怕部分嘲笑不完全是這樣。它們有助於嘲笑抽象類中的一些未實現的方法,但是如果有實現,它仍然會被調用。換句話說,在我的例子中,用MockRepository.GeneratePartialMock ()替換MockRepository.GenerateStub ()不會改變任何東西。 – 2010-03-05 18:28:42

+1

使你的方法虛擬。 – 2010-03-05 22:14:21

3

您必須使方法變爲虛擬。犀牛嘲笑(和大多數其他隔離框架)利用代理類來創建存根/嘲諷。

如果使用TypeMock隔離器就可以,因爲這種隔離框架利用.NET API探查,以打造存根嘲笑什麼/嘲笑

+0

+1。正如OP在他的更新中提到的那樣,這些方法必須是虛擬的。 Moq也是如此,並且(我相信)除了TypeMock Isolator之外的每個.NET隔離框架都是如此。便宜且簡單的解決方法是使方法變爲虛擬(或提取界面)。 – TrueWill 2010-03-05 21:45:36

0

我不認爲有做得比這使得其他的另一種方式你想模擬虛擬的任何方法 - 我相信創建具體類的方法是通過動態地分類被模擬的具體類,然後用你在測試中指定的行爲覆蓋給定的方法,所以這需要一個虛擬方法正常工作。

2

這基本上是正確的,一般都是很好的做法。但是,對於特定類型的編碼,它僅僅是有用的

不要將物體看作是某些「更高能量」可以操縱的物體。相反,把它們想象成可以互相發送信息的自治的'人'。接口表示由單個對象發送的消息。

然後,您使用mock驗證是否發送了正確的消息,而不是提供虛假的依賴關係實現。

理想情況下,您不需要創建與現有類完全匹配的接口 - 而是使用類,該接口以接口的形式聲明其需求。