Android单元测试:Geocoder Mockk报‘Failed matching mocking signature for’错误
问题场景
需要测试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

