java - 使用 Mockito 进行单元测试时避免 final方法?

标签 java unit-testing mockito

<分区>

Mockito 不允许模拟 final 方法。 在代码中使用 final 方法是否被认为是不好的做法?为什么?

我不想仅仅为了让测试代码正常工作而更改实现细节,但是,通常测试框架有这些规则来鼓励更好的编码实践。

最佳答案

final 方法在一般情况下绝对不是坏习惯:它们传达了关于方法的行为和语义的特定信息——也就是说,任何调用该方法的人都将获得该实现。 这正是您试图通过模拟颠覆的属性,因为您正在通过(动态生成的)子类覆盖最终实现以执行 stub 行为。

为此,如果你有一个你控制的实现,你试图用一个 stub 替换测试,它可能不应该是final,因为你把它当作一个非 final 方法自己在你的测试中。您的测试是您的组件的另一个用户,您可以针对该用户进行相应的设计。

在您无法控制的实现中,例如第三方库,PowerMock是模拟构造函数以及 privatestaticfinal 方法的普遍接受的解决方案,可能在 final 中类。不过,PowerMock 确实存在一些危险:

  • mock 有额外的复杂性:PowerMock 通过一个重写类本身的特殊类加载器工作,而不是通过 Java 的 OOP 方法分派(dispatch),因此您必须显式列出调用 的类finalstatic 方法,以便 Powermock 可以替换这些调用。
  • 如果您这样做,模拟您无法控制的类会带来额外的风险:如果 API 或实现以不兼容的方式发生变化,您可能会处于不利的境地。
  • 通过违反 final 修饰符的语义,它可能会使您的代码更难阅读 — 您声明该方法具有一种定义明确的可预测行为,然后围绕您自己的声明进行工作。

就“最佳实践”而言,真正的最佳实践是 OOP 原则 jgitter上面提到:“Program to interfaces, not implementations.”通过依赖显式接口(interface):

也就是说,Mockito stub 具体类的简便性使其成为一个诱人的选择,但请注意,最简单的语义正确答案 可能只是删除 final来自需要 stub 的特定方法。

关于java - 使用 Mockito 进行单元测试时避免 final方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23616285/

相关文章:

java - EasyMock 在 final方法上抛出不兼容的返回值类型

java - Jsf 2.0 填充 h :selectOneMenu to access page

unit-testing - 单元测试真的有用吗?

unit-testing - Clojure:如何在测试中使用夹具

javascript - 每次测试后重置服务对象

java - 使用mockito模拟返回ByteBuffer的方法的响应

java - JInternalFrame 裁剪后的 Windows 外观和感觉

java - 如何使用 Mockito 模拟 void 方法

java - 是否需要为 Mockito.mock() 创建一个接口(interface)或实现类?

java - 我对枚举感到困惑