使用Mockito进行单元测试时,避免使用最终方法?

时间:2014-05-12 18:32:25

标签: java unit-testing mockito

Mockito不允许嘲笑最终方法。 在代码中使用最终方法被认为是不好的做法吗?为什么?

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

3 个答案:

答案 0 :(得分:5)

final方法一般来说绝对不是坏习惯:它们传达了一个关于方法的行为和语义的特定信息 - 即,任何调用该方法的人都将获得完全相同的实现。 这正是您试图通过模拟破坏的属性,因为您通过(动态生成的)子类覆盖最终实现来代替执行存根行为。

为此,如果您有一个实现,您可以控制您尝试使用存根替换测试,那么它可能不应该是final,因为您将其视为非{ {1}}在测试中使用自己的方法。您的测试是组件的另一个用户,也是您可以相应设计的用户。

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

  • 模拟有额外的复杂性:PowerMock通过一个特殊的类加载器来重写类本身,而不是通过Java的OOP方法分派,所以你必须明确列出调用类{{1你正在使用方法和final方法,因此Powermock可以替换这些调用。
  • 如果您这样做,则模拟您无法控制的类会有额外的风险:如果API或实现以不兼容的方式更改,您可能会处于不利的位置。
  • 通过违反final修饰符的语义,可能会使您的代码难以阅读 - 您声明方法有一个明确定义的可预测行为,然后解决您自己的声明。

就“最佳做法”而言,真正的最佳做法是OOP原则jgitter上面提到:“Program to interfaces, not implementations.”依靠显式接口:

也就是说,Mockito存在具体类的简易性使其成为一个诱人的选择,但要注意最简单的语义正确答案可能只是从特定的static删除需要存根的方法。

答案 1 :(得分:2)

我相信使用final关键字是一种很好的方式,可以让未来的开发团队明白特定的方法或类是有意无法覆盖的。这些限制也让我感到烦恼。现代Web容器也代理池化bean(等),同样的问题出现在那里。

我建议调查PowerMock。它们提供了很好地插入Mockito的实现。

https://code.google.com/p/powermock/

- 编辑 -

由于害怕开始圣战,我还想说,通常,你应该在界面中测试暴露的API,并且任何最终方法都将通过该界面间接测试。但是,如果你有一个高风险的方法,那么深入了解它是有用的。

答案 2 :(得分:0)

当您不让其他程序员覆盖该方法时,我发现最终关键字对方法很有用。

例如,我有一个三角类,发现两边的直角三角形的斜边是一边的法律平方根,一边是2的力量,另一边是b的2的幂。那是' sa数学定律。阻止程序员覆盖它并可能犯错误。使方法最终

public class Trig
{
     public final double hytpotenuseOfRightTriangle(double sideA, double sideB)
     {
         return Math.sqrt(Math.pow(sideA, 2) + Math.pow(sideB, 2));
     }
}