5

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

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

使用 Mocks 而不是 Stubs 的一大好处是,我们将能够在所有测试中重用相同的实例,从而使它们更简洁明了。

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

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

4

2 回答 2

6

请记住,Rhino 已不再开发1。较新的框架完全放弃了这种模拟存根差异,并为其测试替身引入了单一术语:

模拟框架的演变似乎朝着“一个通用实体”的方向发展,而不是根据测试用例上下文有不同的不同实体。

要了解更多关于这种分离(模拟、存根、伪造)是如何产生的以及它服务的目的,我建议阅读Mark Seemann关于测试替身连续体的文章:

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


看起来 Rhino 并没有区分 mock 和 stub,但还是有细微差别的。例如,考虑存根属性 getter:

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

这就是当对象是模拟的时候你必须这样做的。另一方面,存根引入了属性语义,它使整个事情变得微不足道:

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

尽管这是我此刻唯一想到的,但可能还有更多。但是,这些只是细微的差别。

1:截至2013年 5 月 19 日,这可能不再适用:犀牛模拟新家

于 2012-09-10T23:44:42.683 回答
3

There is a pretty clear answer in the documentation:

A mock is an object that we can set expectations on, and which will verify that the expected actions have indeed occurred. A stub is an object that you use in order to pass to the code under test. You can setup expectations on it, so it would act in certain ways, but those expectations will never be verified. A stub's properties will automatically behave like normal properties, and you can't set expectations on them.

If you want to verify the behavior of the code under test, you will use a mock with the appropriate expectation, and verify that. If you want just to pass a value that may need to act in a certain way, but isn't the focus of this test, you will use a stub.

IMPORTANT: A stub will never cause a test to fail.

于 2012-09-10T22:28:31.500 回答