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

Mar*_*ira 5 c# tdd unit-testing rhino-mocks mocking

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

总是使用MockRepository.GenerateMock()我们会失去什么?

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

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

(请不要回答有关Fowler的"Mocks are not stubs"文章的链接)

k.m*_*k.m 6

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

模拟框架的演变似乎倾向于"一个通用实体",而不是根据测试用例上下文分别具有不同的实体.

为了更多地了解这种分离(模拟,存根,假)的起源以及它的用途,我建议阅读Mark Seemann关于测试双重连续性文章:

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


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

var mock = MockRepository.GenerateMock<IService>();
mock.Stub(m => m.Property).Return(42);
Run Code Online (Sandbox Code Playgroud)

这是对象模拟时你必须这样做的方法.另一方面,存根引入了属性语义,这使得整个事物变得无足轻重:

var stub = MockRepository.GenerateStub<IService>();
stub.Property = 42;
Run Code Online (Sandbox Code Playgroud)

即使这是目前我脑海中唯一想到的,也可能会有更多.但是,这些只是细微的差别.

1:截至2013年5月19日,这可能不再成立:Rhino Mocks新家


Dav*_*yon 3

文档中有一个非常明确的答案:

模拟是一个我们可以设置期望的对象,它将验证预期的操作是否确实发生了。存根是一个用于传递给被测代码的对象。您可以对它设置期望,因此它会以某些方式起作用,但这些期望永远不会得到验证。存根的属性将自动表现得像普通属性一样,并且您无法对它们设置期望。

如果您想验证被测代码的行为,您将使用具有适当期望的模拟,并进行验证。如果您只想传递一个可能需要以某种方式起作用的值,但不是此测试的重点,那么您将使用存根。

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