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

使用coEvery mock Kotlin挂起函数时实际执行原函数致测试失败

问题分析与解决方案

核心原因

你遇到的mock未生效问题,本质是测试中使用的MyService是真实实例而非mock对象:

  • @Autowired注入的是Spring容器中的真实MyService Bean,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 20:06:21