【问题标题】:Avoid final methods when unit testing with Mockito? [closed]使用 Mockito 进行单元测试时避免使用 final 方法? [关闭]
【发布时间】:2014-05-12 18:32:25
【问题描述】:

Mockito 不允许模拟最终方法。 在您的代码中包含最终方法是否被认为是不好的做法?为什么?

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

【问题讨论】:

  • 我认为(某些)测试框架不支持这一点的原因仅仅是因为创建覆盖最终方法的模拟的技术难度。最终方法不被认为是不好的做法 AFAIK。

标签: java unit-testing mockito


【解决方案1】:

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

为此,如果你有一个你控制的实现,你试图用存根替换测试,它可能不应该是final,因为你将它视为非final方法自己在你的测试。您的测试是您的组件的另一位用户,您可以相应地为其设计。

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

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

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

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

【讨论】:

  • 那么,我们应该在单元测试中使用final 还是不使用?你的回答太圆了。
  • @binary 如果可能,请将final 放在它干扰模拟的地方。否则,将final 与代码库的其余部分保持一致。这应该在第二段和最后一段中得到体现:工程判断的空间,所以很遗憾这不是一个真正的二元答案。
【解决方案2】:

我相信使用 final 关键字是一种很好的方式,可以让未来的开发团队清楚地知道特定方法或类是故意不可覆盖的。这些限制也困扰着我。现代 Web 容器还代理池化 bean(等),同样的问题也发生在那里。

我建议研究一下 PowerMock。他们提供了一个可以很好地插入 Mockito 的实现。

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

-- 编辑--

为了避免引发一场圣战,我还想说,一般来说,你应该在一个接口中测试暴露的 API,任何最终方法都将通过该接口间接测试。但是,如果您有高风险的方法,深入一点是有用的。

【讨论】:

    【解决方案3】:

    当你没有其他程序员重写方法时,我发现 final 关键字对方法很有用。

    例如,我有一个三角学课程,发现直角三角形的 2 边的斜边是 a 边的平方根的 2 次方加上 b 边的 2 次方的定律。这是一个数学定律。阻止程序员重写它并可能犯错误。使方法最终

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-01
      • 2017-06-13
      • 2020-02-22
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      相关资源
      最近更新 更多