android Kotlin中枚举类中缺少分支覆盖

wecizke3  于 2023-05-21  发布在  Android
关注(0)|答案(3)|浏览(109)

我有枚举类

enum class Type(val type: String) {
    ONE("one"),
    TWO("two"),
    THREE("three");

    companion object {
        private val mapByType = Type.values().associateBy(Type::type)
        fun fromType(type: String) = mapByType[type.lowercase()] ?: ONE
    }
}

我创建了一个这样的函数

internal fun handleTypeAction(movieModel: MovieModel) {
    when (movieModel.type) {
        Type.ONE -> xyzfunction()
        Type.TWO -> xyzfunction()
        Type.THREE -> xyzfunction()
    }
}

我知道有三个分支机构。我做了一个这样的测试案例

@Test
    fun `handleTypeAction - WHEN type is ONE THEN should call xyzfunction`() {
        val mockMovieModel = mockk<MovieModel>()
        every { mockMovieModel.type } returns Type.ONE
        subject.handleTypeAction(mockMovieModel)
        verify { subject. xyzfunction() }
    }

    @Test
    fun `handleTypeAction - WHEN type is TWO THEN should call xyzfunction`() {
        val mockMovieModel = mockk<MovieModel>()
        every { mockMovieModel.type } returns Type.TWO
        subject.handleTypeAction(mockMovieModel)
        verify { subject. xyzfunction() }
    }
    
    @Test
    fun `handleTypeAction - WHEN type is THREE THEN should call xyzfunction`() {
        val mockMovieModel = mockk<MovieModel>()
        every { mockMovieModel.type } returns Type.THREE
        subject.handleTypeAction(mockMovieModel)
        verify { subject. xyzfunction() }
    }

我怎么会错过这里的分支呢这里的四个分支覆盖率是多少?

更新

@Keep
@Parcelize
data class MovieModel(
    val actionTitle: String = "",
    val type: Type = Type.ONE,
) : Parcelable
fykwrbwg

fykwrbwg1#

我假设那是Jacoco,但我认为如果你使用其他工具,答案也是一样的。代码覆盖率是基于字节码而不是源代码计算的。如果你分析字节码,你会看到枚举被转换为int[](基于它们的ordinal),事实上编译器在handleTypeAction中生成了4个分支:

TABLESWITCH
  1: L3
  2: L4
  3: L5
  default: L6

Jacoco无法发现default分支实际上是不可能的,所以它将其突出显示为错过的分支。
有趣的是,如果你强制编译器检查穷尽性(下面的例子),覆盖率将达到100%。我会检查为什么会这样,并更新这个答案。
示例:

fun handleTypeAction(movieModel: MovieModel) {
    val x = when (movieModel.type) {
        Type.ONE -> doSomething()
        Type.TWO -> doSomething()
        Type.THREE -> doSomething()
    }
}
x6492ojm

x6492ojm2#

这里的四个分支覆盖率是多少?
可能:null
我没有使用过Jacoco,所以我不知道它是否支持Kotlin。然而,如果它只是查看字节码,它可能无法判断movieModel变量是不可空的。因此,它报告变量可能为null,因此不被处理。

des4xlb0

des4xlb03#

我猜可能是这样的情况,它没有检测到你的when表达式中没有其他状态?

internal fun handleTypeAction(movieModel: MovieModel) {
    when (movieModel.type) {
        Type.ONE -> xyzfunction()
        Type.TWO -> xyzfunction()
        Type.THREE -> xyzfunction()
        else -> throw IllegalStateException(") // Here
    }
}

你也可以试试这个案子。

相关问题