You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Mockk验证接收嵌套数据类参数的Lambda时出现AbstractMethodError问题求助

使用Mockk验证接收嵌套数据类参数的Lambda时出现AbstractMethodError问题求助

我最近写单元测试时碰到个棘手问题:用Mockk验证接收嵌套数据类参数的Lambda调用时,居然抛出了AbstractMethodError,折腾好一阵都没搞定,特意来求助大家!

先给大家看我的测试代码和相关类:

import io.mockk.verify
import org.junit.jupiter.api.Test

class DummyTest {

    @Test
    fun `dummy test to show issue with mockk`() {
        val lambdaFunc: (SomeDataClass) -> Unit = { }
        dummyFunc(lambdaFunc)

        verify(exactly = 1) {
            lambdaFunc(any<SomeDataClass>(any()))     // 用lambdaFunc(any<SomeDataClass>(any<AnotherDataClass>()))会报参数类型不匹配错误
        }
    }
}

data class AnotherDataClass(val arg1: String, val arg2: String)

sealed class SomeSealedClass {
    data class SomeDataClass(val anotherDataClass: AnotherDataClass): SomeSealedClass()
}

fun dummyFunc(
    onEvent: (SomeDataClass) -> Unit
) {
    onEvent(SomeDataClass(AnotherDataClass("arg1", "arg2")))
}

运行测试后得到如下错误栈:

Receiver class kotlin.reflect.KClass$Subclass1 does not define or inherit an implementation of the resolved method 'abstract boolean isValue()' of interface kotlin.reflect.KClass.
java.lang.AbstractMethodError: Receiver class kotlin.reflect.KClass$Subclass1 does not define or inherit an implementation of the resolved method 'abstract boolean isValue()' of interface kotlin.reflect.KClass.
    at io.mockk.impl.recording.JvmSignatureValueGenerator.signatureValue(JvmSignatureValueGenerator.kt:19)
    at io.mockk.impl.recording.states.RecordingState.matcher(RecordingState.kt:46)
    at io.mockk.impl.recording.CommonCallRecorder.matcher(CommonCallRecorder.kt:52)
    at io.mockk.MockKMatcherScope.match(API.kt:695)
    at io.mockk.MockKMatcherScope.any(API.kt:745)
    at com.sarim.puzzle.data.usecase.DummyTest.dummy_test_to_show_issue_with_mockk$lambda$0(DummyTest.kt:16)
    at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:24)
    at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:76)
    at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
    at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:39)
    at io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
    at io.mockk.MockKDsl.internalVerify(API.kt:120)
    at io.mockk.MockKKt.verify(MockK.kt:218)
    at io.mockk.MockKKt.verify$default(MockK.kt:209)
    at com.sarim.puzzle.data.usecase.DummyTest.dummy test to show issue with mockk(DummyTest.kt:15)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at java.base/java.util.ArrayList.forEach(Unknown Source)
    at java.base/java.util.ArrayList.forEach(Unknown Source)

我试过把验证语句改成lambdaFunc(any<SomeDataClass>(any<AnotherDataClass>())),但又会报参数类型不匹配的错误。现在我不确定Mockk是不是支持这种嵌套数据类的参数验证,也不知道该怎么修改那行验证代码才能正常工作。


解决思路和方案

首先得明确:你之前的写法any<SomeDataClass>(any())是错误的,any()这个matcher方法并没有接受另一个matcher作为参数的重载,这种错误用法触发了Mockk内部的反射异常,也就是你看到的AbstractMethodError。

针对你的场景,有两种实用的解决方式:

1. 只验证Lambda被调用次数(不关心参数内容)

如果不需要检查参数具体值,只需要确认Lambda被调用了一次,直接简化验证语句即可:

verify(exactly = 1) {
    lambdaFunc(any())
}

Kotlin会自动推断any()的类型为SomeDataClass,写法简洁且不会出错。

2. 验证嵌套数据类的具体属性值

如果需要确保Lambda被调用时传入的SomeDataClass实例内部的AnotherDataClass属性符合预期,可以用match matcher做自定义检查:

verify(exactly = 1) {
    lambdaFunc(match { dataClass ->
        dataClass.anotherDataClass.arg1 == "arg1" && 
        dataClass.anotherDataClass.arg2 == "arg2"
    })
}

这样就能精准验证嵌套数据类的属性值是否正确,同时避免了之前的错误用法。

另外补充一点:这类反射异常有时候也可能是Mockk版本和Kotlin版本不兼容导致的,建议你确认项目中使用的Mockk版本是否和当前Kotlin版本匹配(比如Mockk 1.13.x对应Kotlin 1.8+,Mockk 1.12.x对应Kotlin 1.7+),如果版本不兼容,升级Mockk到对应版本也能解决问题。

备注:内容来源于stack exchange,提问作者user2287994

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 08:54:32