不同测试双打之间的区别是否重要?

时间:2012-01-11 20:19:24

标签: tdd mocking mockito stub

我刚读了Martin Fowler的帖子Mocks Aren't Stubs。他定义了不同的测试双打(或者更确切地说是参考Gerard Meszaros的xUnit patterns book):

  
      
  • 虚拟对象传递但从未实际使用过。通常他们   仅用于填充参数列表。
  •   
  • 虚假物品实际上有   工作实现,但通常采取一些捷径   它们不适合生产(内存数据库是一个很好的   例)。
  •   
  • Stubs为测试期间拨打的电话提供固定答案,   通常根本没有回应任何程序以外的任何东西   为了测试。存根也可以记录有关呼叫的信息,例如   一个电子邮件网关存根,可以记住它“发送”的消息,或者可能   只发送了多少条消息。
  •   
  • 模拟是......预编程的对象,具有形成的期望   他们应该接收的电话的规范。
  •   

我的问题的第一部分是,这是否具有权威性?这种语言被广泛使用和理解吗?

我的问题的第二部分是,似乎我的选择模拟框架Mockito使模糊线条变得容易,当然在模拟和存根之间。

  • 一切都被称为“模拟”。通过调用Mockito.mock()方法或使用@Mock注释,您可以使用单词“mock”来创建模拟,存根,有时还可以创建虚拟对象(如果简单的“新”不会这样做)。例外是一个“间谍”,它可能用于制作类似“假”的东西,但也可以用来包装你的系统。
  • 即使您不关心创建测试双精度的方法的名称,也可以验证(或不验证)双精度,并且您可以在验证步骤中包含捕获,这似乎包括一些stub会做(记住所做的调用)和模拟(验证已经进行了某些预期的调用)。

我问的原因是我试图根据我上面提到的四个事情来命名我的双打,但有时会混淆某些东西是否真的具有存根或模拟的作用。那么,这是Mockito的缺陷,还是这就是事情的演变方式,这种区别并不重要?

3 个答案:

答案 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可以像假人,存根或间谍一样行事。“

enter image description here

引用和图像均来自this article。恕我直言,模拟旨在模糊虚拟,存根和间谍之间的界限。