我刚读了Martin Fowler的帖子Mocks Aren't Stubs。他定义了不同的测试双打(或者更确切地说是参考Gerard Meszaros的xUnit patterns book):
- 虚拟对象传递但从未实际使用过。通常他们 仅用于填充参数列表。
- 虚假物品实际上有 工作实现,但通常采取一些捷径 它们不适合生产(内存数据库是一个很好的 例)。
- Stubs为测试期间拨打的电话提供固定答案, 通常根本没有回应任何程序以外的任何东西 为了测试。存根也可以记录有关呼叫的信息,例如 一个电子邮件网关存根,可以记住它“发送”的消息,或者可能 只发送了多少条消息。
- 模拟是......预编程的对象,具有形成的期望 他们应该接收的电话的规范。
我的问题的第一部分是,这是否具有权威性?这种语言被广泛使用和理解吗?
我的问题的第二部分是,似乎我的选择模拟框架Mockito使模糊线条变得容易,当然在模拟和存根之间。
我问的原因是我试图根据我上面提到的四个事情来命名我的双打,但有时会混淆某些东西是否真的具有存根或模拟的作用。那么,这是Mockito的缺陷,还是这就是事情的演变方式,这种区别并不重要?
答案 0 :(得分:6)
实际上,这是Mockito的力量。 Mockito mock是一个对象,您可以在其上“存根”方法,或“验证”方法,或两者兼而有之。 (对于相同的方法,两者都是代码味道,但这是另一个主题)。因此,Mockito模拟既是“存根”(在Martin Fowler意义上)又是“模拟”(在Martin Fowler意义上);但你不必同时使用它。通常,Mockito模拟将充当“存根”,或充当“模拟”;两者都不常见。
在其他一些模拟框架中,您没有这种灵活性。如果你想在模拟上进行“验证”,你还必须做“存根”。在这些框架中,模拟必须既作为“存根”又作为“模拟”。据我了解,促使Szczepan Faber创造Mockito的因素之一是希望能够分离“存根”行为和“模拟”行为(严格的Martin Fowler对这两个词的感觉)。
答案 1 :(得分:3)
英文单词“mock”的意思是“模仿质量低于原始的”。这就是为什么即使是手工编织的模拟(没有像Mockito这样的框架的帮助下编写)有时也被称为模拟。
马丁使用的语言现在有点过时了。在“好的模拟”出现之前,他在像JMock这样的旧模拟框架的背景下编写了它。在那个时代,嘲笑过去是严格的;任何尚未建立且未被预期的互动都会失败。
如今我们倾向于以不同的方式来思考它。如果我是一个班级,我还有其他一些课程需要帮助我。他们要么提供信息,要么为我做一些工作 - 例如,存储库可能会提供员工列表,或者保存新员工。
Mocks代表这些合作者,我们不再倾向于对模拟使用期望。相反,我们设置模拟提供信息,然后验证他们被要求做任何需要完成的工作。 Mockito是第一个以这种方式工作的框架,这就是为什么区别模糊 - 因为无论你做什么,你都在嘲笑一个合作者,你不再需要设定期望。 Moq在.NET中的工作方式相同。
默认情况下,Mockito的模拟甚至不关心你是否使用它们并且不检查(尽管你需要设置他们必须提供的任何信息 - 相当于“存根”)。此外,由于Mockito提供“漂亮”的模拟,你不必担心在某个地方使用虚拟对象时设置期望 - 你也可以使用Mockito来创建它们。而且,为了防止你想添加一些简单的行为,Mockito允许你轻松地对传递给它的参数进行回调,这样你就可以创建“Fakes”。
它们究竟是什么并不重要 - 你只是在嘲笑一个合作课程,灵活性意味着你不必担心你是如何做到的。
早期的框架没有提供这种灵活性,因此Martin的差异化旨在帮助您适当地使用模拟。希望这有助于澄清事情并解释为什么Mockito的灵活性不是缺陷,但是 - 正如David Wallace指出的那样 - 一种力量。
答案 2 :(得分:3)
根据我对Gerard Meszaros的X-Unit测试模式的理解,模拟是一个测试双重,包括虚拟,存根和间谍的功能。您可以在该书的第742页中查看他对它们的实际比较。
同样this article可能会对你的问题有所启发。本文明确指出
“模拟是由模拟库动态创建的(其他模拟库是 通常由测试开发人员使用代码生成。测试开发人员 永远不会看到实现接口或基类的实际代码, 但可以配置模拟以提供返回值,特别期望 要调用的成员,等等。根据其配置,a mock可以像假人,存根或间谍一样行事。“
引用和图像均来自this article。恕我直言,模拟旨在模糊虚拟,存根和间谍之间的界限。