22

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 无法拦截对非虚拟方法的调用。所以,我想我要么使用接口,要么使具体类上的每个方法都是虚拟的。如果还有其他选择,请纠正我。

4

5 回答 5

23

Bryan 使用部分模拟的答案是不正确的。这不是部分模拟的用途。

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 框架。它的工作方式与 TypeMock 相同,它使用 .NET 分析器 API 来拦截调用。

Moles 是免费的(目前)。它也是测试版。Moles 仅适用于Microsoft Pex 工具。而且它的 API 明显不如 TypeMock 精致、优雅的 API。

于 2010-03-05T23:23:58.920 回答
3

您必须使方法虚拟化。Rhino 模拟(和大多数其他隔离框架)利用代理类来创建存根/模拟。

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

于 2010-03-05T21:27:20.127 回答
2

这基本上是正确的,并且通常是良好的做法。但是,它仅对特定类型的编码真正有用。

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

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

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

于 2010-03-05T23:59:42.430 回答
1

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

于 2010-03-05T15:57:45.980 回答
0

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

于 2010-03-05T21:29:12.030 回答