犀牛模拟 - 我们真的需要存根吗?

时间:2012-09-10 21:07:01

标签: c# unit-testing mocking tdd rhino-mocks

如果可以使用mock.Stub()更改Rhino Mocks中的模拟行为。返回(),为什么我们还需要Stubs?

总是使用MockRepository.GenerateMock()?

我们会失去什么

使用Mocks而不是Stubs的一大好处是,我们将能够在所有测试中重用相同的实例,使它们更清晰,更直接。

moq框架以类似的方式工作......我们没有针对模拟和存根的不同对象。

(请不要回答Fowler的“Mocks are not stubs”文章的链接)

2 个答案:

答案 0 :(得分:6)

请记住,Rhino不再开发 1 。较新的框架完全放弃了这个模拟 - 存根差异,并为他们的测试双打引入单个术语:

模拟框架的演变似乎倾向于“一个通用实体”,而不是根据测试用例上下文单独使用不同的。

要详细了解这种分离(模拟,存根,假冒)的起源和服务目的,我建议您阅读Mark Seemann's关于continuum of test doubles的文章:

  

在一个极端,你会发现完全没有实现的假人,而另一端则是完整的生产实现。虚拟对象和生产实现都是明确定义的,但是存根,间谍和假货更难以确定:测试间谍什么时候变成假的?另外,模拟在连续体中占据相当大的间隔,因为它们在某些情况下可能相当复杂,但在其他情况下则非常简单。


看起来Rhino似乎没有区分模拟和存根,但存在细微差别。例如,考虑存根属性getter:

var mock = MockRepository.GenerateMock<IService>();
mock.Stub(m => m.Property).Return(42);

当对象被模拟时,你必须这样做。另一方面,Stub引入了属性语义,这使得整个事情变得无足轻重:

var stub = MockRepository.GenerateStub<IService>();
stub.Property = 42;

即使这是目前我脑海中浮现的唯一一个,但可能会有更多。但是,这些只是细微的差别。

1:从 05/19/2013 开始,这可能不再成立:Rhino Mocks new home

答案 1 :(得分:3)

有一个非常明确的答案in the documentation

  

模拟是一个我们可以设定期望的对象,以及将要设置的期望   验证确实发生了预期的操作。存根是一个   您用于传递给测试代码的对象。您可以   设定对它的期望,所以它会以某种方式行动,但那些   期望永远不会得到验证。存根的属性会   自动表现得像普通属性,你无法设置   对他们的期望。

     

如果要验证被测代码的行为,您将会这样做   使用具有适当期望的模拟,并验证。如果你   只想传递一个可能需要以某种方式行动的价值,但是   不是这个测试的重点,你将使用存根。

     

重要提示:存根永远不会导致测试失败。

相关问题