Jacoco 抱怨不太可能丢失分支覆盖
Jacoco complains about unlikely missing branch coverage
我正在使用 Gradle 6.3 和 Jacoco 来编译、测试和显示覆盖率报告。但我不明白为什么它抱怨“错过了 2 个分支中的 1 个”,根本没有分支:
这是完整的 Kotlin 数据class:
data class ListNode<T>(var value: T, var next: ListNode<T>?) {
override fun hashCode(): Int = value.hashCode()
}
如果幕后有分支,它们是什么,我该如何覆盖它们?
Kotlin 中的 data class
具有默认的自动生成方法(equals
、toString
、hashCode
、getter、setter)。在这种情况下,我们谈论的是 equals
。在class ListNode
的代码中是看不到的,但它的JVM字节码肯定包含equals
、toString
等
Jacoco 主要针对 Java Code Coverage,因此,这种情况可能会被视为 Jacoco 对 Kotlin 中生成的方法的错误处理。如果您愿意 - 为项目维护者提交 issue。
无论如何,为了避免 Jacoco 对这种特殊情况发出警告,只需查看报告中的代码(第 17,18 行,.. 直到 equals
方法的末尾):
暂时将生成的equals
方法的内容复制到ListNode
(只是为了自己方便)
将代码覆盖率增加到需要的水平
擦除equals
方法
代码覆盖率与步骤 (2) 相同,因为 equals
保持不变(但现在它是隐式创建的)
字节码中实际上有两个分支,原因如下。
您正在 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>?)
我正在使用 Gradle 6.3 和 Jacoco 来编译、测试和显示覆盖率报告。但我不明白为什么它抱怨“错过了 2 个分支中的 1 个”,根本没有分支:
这是完整的 Kotlin 数据class:
data class ListNode<T>(var value: T, var next: ListNode<T>?) {
override fun hashCode(): Int = value.hashCode()
}
如果幕后有分支,它们是什么,我该如何覆盖它们?
Kotlin 中的 data class
具有默认的自动生成方法(equals
、toString
、hashCode
、getter、setter)。在这种情况下,我们谈论的是 equals
。在class ListNode
的代码中是看不到的,但它的JVM字节码肯定包含equals
、toString
等
Jacoco 主要针对 Java Code Coverage,因此,这种情况可能会被视为 Jacoco 对 Kotlin 中生成的方法的错误处理。如果您愿意 - 为项目维护者提交 issue。
无论如何,为了避免 Jacoco 对这种特殊情况发出警告,只需查看报告中的代码(第 17,18 行,.. 直到 equals
方法的末尾):
暂时将生成的
equals
方法的内容复制到ListNode
(只是为了自己方便)将代码覆盖率增加到需要的水平
擦除
equals
方法代码覆盖率与步骤 (2) 相同,因为
equals
保持不变(但现在它是隐式创建的)
字节码中实际上有两个分支,原因如下。
您正在 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
. 测试 - 使用
Any
作为T
的上限:
ListNode
的其他分支
data class ListNode<T: Any>(var value: T, var next: ListNode<T>?)