【问题标题】:Jacoco complains about unlikely missing branch coverageJacoco 抱怨不太可能缺少分支覆盖
【发布时间】:2020-04-12 08:01:42
【问题描述】:

我正在使用 Gradle 6.3 和 Jacoco 来编译、测试和显示覆盖率报告。但我不明白为什么它抱怨“错过了 2 个分支中的 1 个”,根本没有分支:

这是完整的 Kotlin 数据类:

data class ListNode<T>(var value: T, var next: ListNode<T>?) {

    override fun hashCode(): Int = value.hashCode()

}

如果幕后有树枝,它们是什么,我该如何遮盖它们?

【问题讨论】:

    标签: java kotlin jacoco


    【解决方案1】:

    字节码中实际上有两个分支,原因如下。

    您在Any? 上使用扩展名hashCode(),因为T 的上限是Any?,而不是Any。这个扩展是这样实现的:

    public inline fun Any?.hashCode(): Int = this?.hashCode() ?: 0
    

    这意味着在字节码中,您对value.hashCode() 的调用被替换为value?.hashCode() ?: 0

    在您的测试中,您仅涵盖value 可能不为空的情况,因此未涵盖分支?: 0

    在 JaCoCo 不支持 inline 函数之前,您有两种解决方案:

    • 还覆盖另一个使用null T 测试ListNode 的分支。
    • 使用Any 作为T 的上限:
    data class ListNode<T: Any>(var value: T, var next: ListNode<T>?)
    

    【讨论】:

    • 感谢 Giorgio,给了如此清晰的答案!
    • @adamsmith 没问题!
    【解决方案2】:

    Kotlin 中的 data class 具有默认的自动生成方法(equalstoStringhashCode、getter、setter)。在这种情况下,我们谈论的是equals。在class ListNode的代码中是看不到的,但它的JVM字节码肯定包含equalstoString等。

    Jacoco 主要针对 Java Code Coverage,所以这种情况可能会被视为 Jacoco 对Kotlin 中生成的方法。如果您愿意,请为项目维护者提交 issue

    无论如何,为了避免 Jacoco 对这种特殊情况发出警告,只需查看报告中的代码(第 17,18 行,.. 直到 equals 方法的末尾):

    1. 将生成的equals方法的内容临时复制到ListNode(只是为了自己方便)

    2. 将代码覆盖率提高到所需水平

    3. 清除equals方法

    4. 代码覆盖率保持与步骤 (2) 相同,因为 equals 保持不变(但现在它是隐式创建的)

    【讨论】:

      猜你喜欢
      • 2019-09-13
      • 2013-05-03
      • 2015-10-31
      • 2018-06-25
      • 1970-01-01
      • 2016-08-11
      • 2023-03-03
      • 1970-01-01
      • 2021-11-30
      相关资源
      最近更新 更多