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

调用私有挂起函数时参数不匹配,求助排查缺失的第三个参数

问题:调用私有挂起函数时触发参数不匹配异常

我使用扩展函数调用ViewModel中的私有挂起函数setUpArea(areaId: Long),调用代码为viewModel.callPrivateFunc("setUpArea", 2L),运行测试时抛出IllegalArgumentException,提示“Callable expects 3 arguments, but 2 were provided”,无法确定缺失的第三个参数。

相关代码

测试代码

@Before
fun setUp() {
    savedStateHandle = SavedStateHandle()
    savedStateHandle["areaId"] = 1L
    saveImageUseCase = Mockito.mock(SaveImageUseCase::class.java)
    repo = FakeRepository()
    viewModel = AreaEditViewModel(repo, savedStateHandle, saveImageUseCase)
}

@Test
fun setUpArea() = runTest {
    viewModel.callPrivateFunc("setUpArea", 2L)
}

ViewModel代码

private suspend fun setUpArea(areaId: Long) {
    repository.getAreaById(areaId).first() {
        savedStateHandle["area"] = it
        true
    }
}

原因分析

Kotlin的挂起函数会被编译器自动注入一个Continuation类型的参数,这是协程实现挂起/恢复逻辑的底层机制。因此你定义的setUpArea(areaId: Long)在编译后,实际方法签名会变成setUpArea(Long, Continuation<? super Unit>)。

而你使用的扩展函数在反射调用时,只传入了areaId参数,没有提供这个隐式的Continuation参数,加上成员方法反射调用时需要传入实例本身作为第一个参数,就导致了“期望3个参数(实例、areaId、Continuation)但只传入了2个(实例、areaId)”的异常。

解决方案

要正确调用私有挂起函数,需要修改扩展函数以支持协程,这里提供适配挂起函数的扩展函数实现:

import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext

suspend fun <T : Any> T.callPrivateSuspendFunc(name: String, vararg args: Any?): Any? {
    val continuation = Continuation(EmptyCoroutineContext) { result ->
        result.getOrThrow()
    }
    val methodParams = args.map { it?.javaClass } + Continuation::class.java
    val method = javaClass.getDeclaredMethod(name, *methodParams.toTypedArray())
    method.isAccessible = true
    return method.invoke(this, *args, continuation)
}

然后在测试中这样调用:

@Test
fun setUpArea() = runTest {
    viewModel.callPrivateSuspendFunc("setUpArea", 2L)
}

内容的提问来源于stack exchange,提问作者RCH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:31:08