我读过各种关于测试中模仿和存根的文章,包括Martin Fowler的《Mocks Aren't Stubs》,但我仍然不理解其中的区别。
当前回答
我认为他们之间最重要的区别是他们的意图。
让我试着用WHY stub和WHY mock来解释它
假设我正在为我的mac twitter客户端的公共时间轴控制器编写测试代码
下面是测试示例代码
twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
STUB:到twitter API的网络连接非常慢,这使得我的测试很慢。我知道它将返回时间轴,所以我制作了一个模拟HTTP twitter API的存根,这样我的测试将非常快地运行它,即使我离线也可以运行测试。 MOCK:我还没有写任何我的UI方法,我不确定我需要为我的UI对象写什么方法。我希望通过编写测试代码了解我的控制器如何与我的ui对象协作。
通过编写mock,您可以通过验证期望是否满足来发现对象的协作关系,而stub仅模拟对象的行为。
如果您想了解更多关于模拟的知识,我建议您阅读这篇文章:http://jmock.org/oopsla2004.pdf
其他回答
以下是我的理解……
如果您在本地创建测试对象并将其提供给本地服务,则使用的是模拟对象。 这将为您在本地服务中实现的方法提供测试。 它用于验证行为 当您从真正的服务提供者获得测试数据时(尽管是从接口的测试版本获得对象的测试版本),您是在使用存根 存根可以有逻辑来接受特定的输入并给出相应的输出来帮助您执行状态验证…
有很多很棒的答案,我喜欢这个,所以我把它做成了一个表格。
Dummy | Stub | Mock | Fake | |
---|---|---|---|---|
API | O | O | O | O |
States | X | O | O | O |
Values | X | X | O | O |
Behavior | X | X | X | O |
关于这个问题,我认为Roy Osherove在他的书《单元测试的艺术》(85页)中给出了最简单、最清晰的答案。
判断我们正在处理存根的最简单方法是注意到存根永远不会通过测试。测试使用的断言总是反对的 被测试的班级。 另一方面,测试将使用一个模拟对象来验证 测试是否失败。[…] 同样,模拟对象是我们用来检查测试是否失败的对象。
Stub和mock都是假的。
如果您对假的进行断言,这意味着您将假的用作mock,如果您仅使用假的运行测试而没有对其进行断言,那么您将假的用作存根。
使用一个心智模型确实帮助我理解了这一点,而不是所有的解释和文章,这些都不能“理解”。
想象一下,你的孩子桌子上有一个玻璃盘子,他开始玩它。现在,你害怕它会破裂。所以,你给了他一个塑料盘子。这将是一个Mock(相同的行为,相同的接口,“更软的”实现)。
现在,假设你没有塑料替代品,所以你解释说“如果你继续玩它,它会碎的!”这是一个Stub,您预先提供了一个预定义的状态。
哑巴就是他根本不用的叉子…间谍可能是提供你已经使用过的有效解释。
Stubs vs. Mocks Stubs provide specific answers to methods calls ex: myStubbedService.getValues() just return a String needed by the code under test used by code under test to isolate it cannot fail test ex: myStubbedService.getValues() just returns the stubbed value often implement abstract methods Mocks "superset" of stubs; can assert that certain methods are called ex: verify that myMockedService.getValues() is called only once used to test behaviour of code under test can fail test ex: verify that myMockedService.getValues() was called once; verification fails, because myMockedService.getValues() was not called by my tested code often mocks interfaces
推荐文章
- 比较Java中2个XML文档的最佳方法
- 如何模拟低带宽、高延迟的环境?
- 使用Moq验证方法调用
- 我如何“休眠”Dart程序
- 使用Mockito的泛型“any()”方法
- Mockito中检测到未完成的存根
- 尝试模拟datetime.date.today(),但不工作
- 如何用python timeit对代码段进行性能测试?
- 确定bash中是否存在一个函数
- 如何使用“测试”包打印Go测试?
- 如何在IntelliJ中为整个项目配置“缩短命令行”方法
- toBe(true) vs toBeTruthy() vs toBeTrue()
- 使用Mockito测试抽象类
- 什么时候应该使用Debug.Assert()?
- 使用Moq模拟扩展方法