【问题标题】:Do contract tests necessary imply stubs?必要的合同测试是否意味着存根?
【发布时间】:2012-11-21 10:54:20
【问题描述】:

最近,我阅读了很多关于合同和协作测试的文章(主要来自 J.B. Rainsberger)。为了融入其中,我开始了一个小项目。

据我了解,契约测试的职责是确保实现尊重其接口固有契约。换句话说,它鼓励了 Liskov 替换原则。

基本上,嘲笑对象合作者就是对它做出假设。现在,如果这些假设发生变化会发生什么?如果我像这样使用 Mockito 模拟协作者(这与存根相同):

 when(collaborator.doSomething(someArgument)).thenReturn(someValue);

当我修改协作者界面(即它的合同)时,我将无法注意到这些变化。

所以这是我的问题:当伪造一个为被测系统提供间接输入的合作者时,是否应该使用存根来防止未注意到的接口/合同更改?

以下是我已经检查过的一些链接:

removing-the-integration-test-scam-understanding-collaboration-and-contract

writing contract tests in java differently

我希望我足够清楚,如果没有,我会尽我所能使其更加透明。提前感谢大家。

【问题讨论】:

  • 我相信这更适合程序员而不是 SO - 阅读他们的faq

标签: unit-testing testing mocking tdd stubs


【解决方案1】:

存根和模拟之间有明显的区别。

存根是替代品,不能改变测试结果。例如,传递给主题的输入参数。

另一方面,模拟可能无法通过测试。它是测试对象之间协作的基础。如果没有达到预期的协作,测试应该会失败。

因此,就您的问题而言,对系统的间接输入应该是存根。

【讨论】:

  • 由于需要解释模拟和存根之间的区别,它只是部分回答了这个问题。 1)模拟与存根问题与处理合同更改是正交的,模拟和存根将在编译时检测到相同的合同修改,并且 2)无论如何它们都不会检测到更微妙的合同更改,所以你必须有一些其他的一种应对它们的策略。
【解决方案2】:

JB Rainsberger 的一篇文章似乎准确地回答了您的问题:Who Tests The Contract Tests ?

所以这是我的问题:在伪装合作者时是否正确 它为被测系统提供间接输入,应该使用 存根以防止被忽视的接口/合同更改?

使用存根而不是什么?

嘲讽?正如@bryanbcook 所指出的那样,这并没有太大的区别,无论如何,存根在这种情况下更合适。

甚至没有实现与合作者相同的基类的手动假类?当然。

IMO 有 2 种合同变更:

  • “硬”更改,即协作者方法的返回类型或参数类型的更改。这些修改很容易 - 它们不会被忽视,因为您的测试甚至不会再编译,只要您的假合作者实现与真正合作者相同的接口/基类

  • “软”更改,即协作者返回给定值或其他值的条件的更改,协作者可以返回或接受的值范围的更改,可能引发的异常等的更改。这些更难发现,但根据上述文章,可以通过在合同测试和协作测试之间执行严格的对应来避免它们。

【讨论】:

  • 非常有趣的评论。我刚刚读过一篇 JB Rainsberger 同意的类似文章。基本上,如果您足够严格,则不需要对每个间接输入进行存根,这是一个平衡问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 2019-03-10
相关资源
最近更新 更多