模拟ScheduledExecutorService与你不拥有的" Don模拟类型#34;哲学

时间:2017-11-21 09:27:43

标签: java unit-testing mocking mockito

模拟ScheduledExecutorService真的会让我的类更容易测试,但是根据mockito recommendations这似乎是一个坏主意,因为模拟类的逻辑可能会以某种方式改变一种不正确的方式,但单元测试仍然会报告成功。

似乎为它编写包装将是" clean"但是我觉得这只会导致界面的完全重复,这会让我的代码变得不那么简单。我希望遵循this answer的实际建议,但我不确定ScheduledExecutorService的合同是否始终保持不变。

我可以假设ScheduledExecutorService(或更一般地说,JRE库中的任何其他类)的现有方法的合同永远不会改变吗?如果没有,如果我在集成测试中测试它的正确使用是否足够,同时仍然在单元测试中直接嘲笑它?

2 个答案:

答案 0 :(得分:2)

我说"不要模仿你不拥有的模型!" 是正确推理中的错误结论。

如果您的 API发生变化,或者您的代码使用依赖部分,则只需要更改单元测试。

例:
  

您将依赖关系的接口作为输入参数,但您测试的代码在该接口中仅使用一种方法。如果你没有模仿这个界面(这是你不拥有的类型),你必须创建自己的虚拟实现,实现所有的接口方法,即使是那些你没有&# 39; t use。

     

如果更改该依赖项的版本,则此接口可能具有其他方法和/或某些方法已被删除。您必须在整个程序中更改您的此接口的所有实现。如果您嘲笑此界面,则无需更改测试,但仍然可以确保您的代码行为在所需的重构后没有发生变化。

此外,您的Unittest应该只会失败,因为您的代码的行为发生了变化,而不是因为依赖行为的变化。 依赖行为的变化应该使用单独的Unittest来设置依赖行为(如果它对您的应用程序至关重要)和/或集成测试

答案 1 :(得分:2)

这更像是一条准则,而不是一条规则;做最有可能导致干净,可靠和非脆弱测试的事情。与您引用的文件一样:

  

这不是一个强硬路线,但越过这条线可能会产生影响! (很可能会)

这里有一个重要的事情是“不要模拟你不拥有的类型”通常是指具体内部类型,因为那些更有可能更改版本之间的行为,或获取或丢失Mockito动态覆盖可能无法接受的finalstatic等修饰符。毕竟,如果你手动子类化第三方类,Java会抛出编译器错误; Mockito的语法会将这一点隐藏起来直到测试运行时。

列出我想到的因素:

  • 正如assylias在评论中指出的那样,您指的是Java界面,它使您免受final方法或方法可见性的常见更改。
  • 该接口有详细记录,专为第三方扩展而设计,这也是Java不太可能对接口的一般合同进行重大更改的另一个原因。
  • 有问题的界面是Java中非常常用的界面,整体上有很多用户,并且有许多向后兼容性问题。与较小的库或正在开发的库相比,您不太可能受到重大变化的影响。有人甚至可能会说JRE处于Java语言的锁定阶段,您可以通过打破语法更改而不是打破 interface 更改来担心。

虽然我强烈反对“不要嘲笑你不拥有的类型”作为一般的启发式或代码味道,但我同意你的意见,这种类型值得嘲笑,除非你要写并测试一个完整的实现,用于其他测试 - 这是你在这里的最佳途径。