【问题标题】:Use of an interface in unit tests在单元测试中使用接口
【发布时间】:2016-10-06 05:03:39
【问题描述】:

为什么建议在使用 Mockito 框架进行单元测试时使用接口?接口在单元测试中的用途到底是什么?

【问题讨论】:

  • 如果被测类接受接口作为参数,我会说你总是想模拟一个接口而不是一个具体的类。如果您模拟接口的特定实现,那么它可能会让其他人阅读代码,例如被测类只接受该实现作为参数。如果有人在被测代码中做了一些讨厌的事情,例如将接口参数转换为特定的具体实现(这将导致类转换异常),那么模拟接口也会暴露。

标签: java testing junit mockito


【解决方案1】:

有两个原因:一个是理论上的,一个是实际的。

理论

在使用模拟时,您提供了一个组件的测试替身,该组件已存在(或将存在)在应用程序的其他地方;存根时,您正在模拟实际实现的响应,并且在验证您是否针对类的外部接口这样做时。这使得明确定义接口的成功实现者应该做什么以及他们应该如何表现非常重要,无论当前的实现如何:你是提供不同的实现。

虽然您可以在具体类本身上逐个记录实现的合同方法,但记录和形式化组件的一般合同的另一种方法是提取接口。虽然我不支持未来的工作(请参阅YAGNI),但如果您要部分或全部用另一个实现替换当前的具体实现,这样做也会更清楚——此时您将拥有接口的三个实现,包括模拟,并且可能想编写一个纯粹针对接口的测试,并分别传递每个实现以在它们之间进行验证/验证。

练习

在内部,Mockito 通过生成您要测试的类的子类 动态创建您的测试替身。这意味着您的 mock 只能覆盖普通子类可以覆盖的行为,这会使 Mockito 不适合私有类、封装的嵌套或内部类以及最终类。此外,出于类似的原因,您会发现自己无法模拟静态方法、最终方法以及一些私有或受保护方法(尤其是编译器生成synthetic methods 的任何位置)。由于 Mockito 的语法和动态特性,Java 无法在编译时警告或强制执行这些规则,而 Mockito 也无法始终在运行时检测违规行为。

然而,当模拟接口而不是具体的实现时,Mockito 可以避免很多这样的麻烦。接口没有内部方法可见性限制或最终方法,并且类型本身必须是公共的和非最终的。因此,从实际的角度来看,接口带来的简单性和易于工作的优势,而不是具体的类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2012-11-27
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多