我读过各种关于测试中模仿和存根的文章,包括Martin Fowler的《Mocks Aren't Stubs》,但我仍然不理解其中的区别。
当前回答
前言
有几个对象的定义是不真实的。一般的术语是双重测试。这个术语包括:dummy, fake, stub, mock。
参考
根据Martin Fowler的文章:
Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists. Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example). Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'. Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
风格
模拟vs存根=行为测试vs状态测试
原则
根据每个测试只测试一件事的原则,一个测试中可能有几个存根,但一般只有一个mock。
生命周期
使用存根测试生命周期:
准备正在测试的对象和它的存根合作者。 锻炼——测试功能。 验证状态——使用断言来检查对象的状态。 Teardown -清理资源。
使用mock测试生命周期:
设置数据-准备正在测试的对象。 设置期望-在mock中准备主对象使用的期望。 锻炼——测试功能。 验证期望——验证在mock中调用了正确的方法。 验证状态——使用断言来检查对象的状态。 Teardown -清理资源。
总结
模拟测试和存根测试都给出了这个问题的答案:结果是什么?
使用模拟进行测试也感兴趣:结果是如何实现的?
其他回答
测试双打:
Fake: Fakes are objects that have working implementations, but not the same as production one. Such as: in-memory implementation of Data Access Object or Repository. Stub: Stub is an object that holds predefined data and uses it to answer calls during tests. Such as: an object that needs to grab some data from the database to respond to a method call. Mocks: Mocks are objects that register calls they receive. In test assertion, we can verify on Mocks that all expected actions were performed. Such as: a functionality that calls e-mail sending service. for more just check this.
下面是对每一个的描述,然后是真实世界的样本。
Dummy - just bogus values to satisfy the API. Example: If you're testing a method of a class which requires many mandatory parameters in a constructor which have no effect on your test, then you may create dummy objects for the purpose of creating new instances of a class. Fake - create a test implementation of a class which may have a dependency on some external infrastructure. (It's good practice that your unit test does NOT actually interact with external infrastructure.) Example: Create fake implementation for accessing a database, replace it with in-memory collection. Stub - override methods to return hard-coded values, also referred to as state-based. Example: Your test class depends on a method Calculate() taking 5 minutes to complete. Rather than wait for 5 minutes you can replace its real implementation with stub that returns hard-coded values; taking only a small fraction of the time. Mock - very similar to Stub but interaction-based rather than state-based. This means you don't expect from Mock to return some value, but to assume that specific order of method calls are made. Example: You're testing a user registration class. After calling Save, it should call SendConfirmationEmail.
存根和Mock实际上是Mock的子类型,两者都交换了实际实现和测试实现,但出于不同的、特定的原因。
这张幻灯片很好地解释了主要的区别。
*选自CSE 403第16讲,华盛顿大学(幻灯片由“Marty Stepp”制作)
Stub
我相信最大的区别是您已经编写了带有预定行为的存根。所以你会有一个实现依赖的类(很可能是抽象类或接口),你是为了测试目的而伪造的,方法只是用设置的响应来存根。它们不会做任何花哨的事情,而且您应该已经在测试之外为它编写了存根代码。
Mock
模拟是测试的一部分,你必须根据你的期望来设置。mock并不是预先设定好的,所以您可以在测试中使用它。模拟在某种程度上是在运行时确定的,因为设置期望的代码必须在它们执行任何操作之前运行。
mock和stub的区别
使用模拟编写的测试通常遵循初始化->设置期望->练习->验证模式进行测试。而预先编写的存根将遵循初始化->练习->验证。
mock和stub之间的相似性
这两种方法的目的都是为了消除对类或函数的所有依赖项的测试,从而使您的测试在试图证明的内容方面更加集中和简单。
关于这个问题,我认为Roy Osherove在他的书《单元测试的艺术》(85页)中给出了最简单、最清晰的答案。
判断我们正在处理存根的最简单方法是注意到存根永远不会通过测试。测试使用的断言总是反对的 被测试的班级。 另一方面,测试将使用一个模拟对象来验证 测试是否失败。[…] 同样,模拟对象是我们用来检查测试是否失败的对象。
Stub和mock都是假的。
如果您对假的进行断言,这意味着您将假的用作mock,如果您仅使用假的运行测试而没有对其进行断言,那么您将假的用作存根。
推荐文章
- ReferenceError: description没有定义NodeJs
- Mock vs MagicMock
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 如何检查动态附加的事件监听器是否存在?
- 强制重新测试或禁用测试缓存
- 比较Java中2个XML文档的最佳方法
- 如何模拟低带宽、高延迟的环境?
- 使用Moq验证方法调用
- 我如何“休眠”Dart程序
- 使用Mockito的泛型“any()”方法
- Mockito中检测到未完成的存根
- 尝试模拟datetime.date.today(),但不工作
- 如何用python timeit对代码段进行性能测试?
- 确定bash中是否存在一个函数
- 如何使用“测试”包打印Go测试?