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

Android单元测试:Geocoder Mockk报‘Failed matching mocking signature for’错误

解决Android Geocoder API挂起函数单元测试的Mockk匹配失败问题

问题场景

需要测试Android API 33+的Geocoder挂起函数:

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private suspend fun Geocoder.getFromLocationApi33(
    latitude: Double,
    longitude: Double
) = suspendCancellableCoroutine { continuation ->
    this.getFromLocation(latitude, longitude, MAX_RESULTS) { addresses ->
        continuation.resumeWith(Result.success(addresses.firstOrNull()))
    }
}

编写的单元测试代码如下:

val geocoder = mockk<Geocoder>()
val addressSlot = slot<(MutableList<Address>) -> Unit>()
coEvery {
    geocoder.getFromLocation(0.0, 0.0, 1, capture(addressSlot))
}.answers {
    addressSlot.captured.invoke(mutableListOf())
}

执行测试时,coEvery行抛出匹配失败错误:

Failed matching mocking signature for SignedCall(retValue=,
isRetValueMock=true, retType=class kotlin.Unit, self=Geocoder(#5),
method=getFromLocation(Double, Double, Int, GeocodeListener),
args=[0.0, 0.0, 1,
com.weatherxm.util.GeocoderCompatTest$1$2$2$3$1$1$$Lambda$314/0x000000010059eab8@73c3ceb5],
invocationStr=Geocoder(#5).getFromLocation(0.0, 0.0, 1,
com.weatherxm.util.GeocoderCompatTest$1$2$2$3$1$1$$Lambda$314/0x000000010059eab8@73c3ceb5))
left matchers: [slotCapture()]

解决方案

核心问题是参数类型不匹配:
你测试代码中用的是(MutableList<Address>) -> Unit类型的slot,但Geocoder API 33的getFromLocation方法的第四个参数是GeocodeListener接口,并非普通Lambda函数类型。

修正后的测试代码:

val geocoder = mockk<Geocoder>()
val listenerSlot = slot<GeocodeListener>()

coEvery {
    geocoder.getFromLocation(0.0, 0.0, 1, capture(listenerSlot))
}.answers {
    // 调用监听器的onGeocode方法返回模拟结果
    listenerSlot.captured.onGeocode(mutableListOf())
}

额外注意事项:

  • 若代码中MAX_RESULTS常量值不是1,需将测试中的第三个参数改为与常量一致的值,避免参数匹配失败
  • 如需测试有返回地址的场景,只需把mutableListOf()替换为包含模拟Address对象的列表即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:23:13