使用coEvery mock Kotlin挂起函数时实际执行原函数致测试失败
问题分析与解决方案
核心原因
你遇到的mock未生效问题,本质是测试中使用的MyService是真实实例而非mock对象:
@Autowired注入的是Spring容器中的真实MyServiceBean,MockK的coEvery只能对mock实例生效,对真实对象的行为设置完全无效,因此会执行原函数的HTTP请求逻辑。- 不用
lateinit的话,Spring无法在测试初始化阶段注入mock实例(mock是动态生成的,无法在类初始化时赋值),进一步导致注入真实对象。
解决方案
方案1:Spring Boot测试场景(启动上下文)
用@MockBean替代@Autowired,让Spring自动将MyService替换为MockK的mock实例,同时配合lateinit var声明:
@SpringBootTest class YourTestClass { @MockBean private lateinit var myService: MyService @Test fun testUpperFunction() = runTest { // 设置mock行为 coEvery { myService.fetchData("valid_token") } returns DataResponse(user_id=1, user_name="test") // 调用上层函数并验证结果 val result = yourUpperService.invokeFetchLogic("valid_token") assertEquals(DataResponse(user_id=1, user_name="test"), result) // 验证mock被正确调用 coVerify(exactly = 1) { myService.fetchData("valid_token") } } }
方案2:普通单元测试(不启动Spring上下文)
直接手动创建MockK的mock实例,无需依赖Spring注入:
class YourTestClass { private val myService = mockk<MyService>() @Test fun testUpperFunction() = runTest { coEvery { myService.fetchData("valid_token") } returns DataResponse(user_id=1, user_name="test") // 手动将mock实例注入到上层服务(比如构造注入) val upperService = UpperService(myService) val result = upperService.invokeFetchLogic("valid_token") assertEquals(DataResponse(user_id=1, user_name="test"), result) coVerify(exactly = 1) { myService.fetchData("valid_token") } } }
关键注意点
- 确保所有对
myService的行为设置(coEvery)和验证(coVerify)都是针对同一个mock实例。 - 如果使用Spring测试,需确保项目中引入
io.mockk:mockk-spring依赖,让MockK作为Spring的mock提供者。
内容的提问来源于stack exchange,提问作者William Ross
相关产品推荐
相关产品推荐

