MockK中any<Class<*>>无法Mock重载方法,需指定具体类问题
问题原因分析
MockK处理泛型重载方法时,受JVM类型擦除机制限制,加上匹配器的泛型推断模糊,会无法准确识别目标重载方法。当使用any<Class<*>>()这类通配符匹配器时,MockK无法将其与方法定义中的泛型参数<T, E>明确关联,进而匹配不到第二个重载的call方法,最终抛出no answer found异常。
而指定具体类时能成功,是因为明确的类型信息帮MockK锁定了对应的方法签名,消除了推断歧义。
解决方案
以下几种方法可在不硬编码类名的前提下解决问题:
1. 显式指定泛型参数 + 类型安全匹配器
在every块中明确指定方法的泛型参数<T, E>,同时为Class类型参数使用带具体泛型的any()匹配器,让MockK准确识别目标重载方法。如果是工具模块,可通过**内联函数+具体化泛型(reified)**动态传递类型:
// 通用工具方法:通过reified泛型动态获取类型 inline fun <reified T : Any, reified E : Any> mockRestCallerOverload( restCaller: RestCaller, mockResponse: T ) { every { restCaller.call<T, E>( any(), any(), any<Class<T>>(), any<() -> Response>(), any<Class<E>>(), any<(E) -> ErrorModel<*>>() ) } returns mockResponse } // 使用时直接传入泛型,无需硬编码类名 mockRestCallerOverload<SomeResponse, ErrorType>(restCaller, mockk<SomeResponse>())
2. 为函数类型匹配器显式指定类型
第二个重载方法包含() -> Response和(E) -> ErrorModel<*>这类函数类型参数,单纯用any()可能导致MockK类型推断偏差。显式指定这些参数的匹配器类型,能帮助MockK更精准匹配方法签名:
every { restCaller.call( any(), any(), any<Class<*>>(), any<() -> Response>(), // 显式指定函数类型 any<Class<*>>(), any<(Any) -> ErrorModel<*>>() // 显式指定转换器类型 ) } returns mockk<SomeResponse>()
3. 针对复现代码的修复
你的复现代码问题出在allAny()的使用以及泛型推断模糊,修改为以下写法即可正常工作:
@Test fun test() { // 显式指定泛型参数,并为每个Class参数指定匹配器类型 every { restCaller.call<String, String>(any(), any<Class<String>>(), any<Class<String>>()) } .returns("some result") val actual = component.someMethod() actual.shouldBe("some result") }
如果要做成通用工具,同样用内联reified函数封装:
inline fun <reified R : Any, reified E : Any> mockSimpleCall( restCaller: RestCaller, result: R ) { every { restCaller.call<R, E>(any(), any<Class<R>>(), any<Class<E>>()) } returns result } // 测试中调用 mockSimpleCall<String, String>(restCaller, "some result")
内容的提问来源于stack exchange,提问作者Sobik
相关产品推荐
相关产品推荐

