Rhino Mocks存根和模拟只适用于接口?

时间:2010-03-05 15:56:29

标签: .net unit-testing mocking rhino-mocks stubbing

Rhino Mocks存根和模拟只对接口有用,而不是具体类吗?我花了很多时间试图让这段代码工作。我没想到存根的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运行相同的测试时,它似乎正在按预期工作。

这是否意味着我必须为我想要使用Rhino模拟/存根的每个类提取接口?或者我在技术上或概念上遗漏了什么?

更新:好的,我似乎弄明白了我缺少的部分: Rhino Mocks无法拦截对非虚方法的调用。所以,我想我要么使用接口,要么在具体类虚拟上使用每个方法。如果还有其他选择,请纠正我。

5 个答案:

答案 0 :(得分: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()

如Jon所说,TypeMock可以伪装这些。

应该注意的是,有一个额外的模拟框架可以拦截所有调用:Microsoft Moles framework。它的工作方式与TypeMock相同,它使用.NET Profiler API来拦截调用。

Moles是免费的(暂时)。它也是测试版。 Moles仅适用于Microsoft Pex tools。它的API明显不如TypeMock精致优雅的API。

答案 1 :(得分:3)

你必须使这些方法成为虚拟的。 Rhino模拟(以及大多数其他隔离框架)利用代理类来创建存根/模拟。

如果你使用TypeMock Isolator,你可以模拟任何东西,因为这个隔离框架利用.NET Profiler API来创建它的'stubs / mocks

答案 2 :(得分:2)

这基本上是正确的,通常是很好的做法。但是,对于特定类型的编码,它只是有用的

不要将对象视为某些“更高权力”可以操纵的东西。相反,将它们视为可以向对方发送消息的自主“人”。接口表示单个对象发送的消息。

然后使用模拟来验证是否发送了正确的消息,而不是提供虚假的依赖实现。

理想情况下,您不会创建与现有类完全匹配的接口 - 而是使用接口的类以接口的形式声明其需求。

答案 3 :(得分:1)

部分模拟允许您模拟具体类的功能。请参阅:http://www.ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx

答案 4 :(得分:0)

我认为除了制作任何你想要模拟虚拟的方法之外还有另一种做法 - 我相信创建具体类的模式的方法是动态地对被模拟的具体类进行子类化,然后覆盖给定具有您在测试中指定的行为的方法,因此这需要虚拟方法才能正常工作。