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

Mockk模拟Ktor HttpClient.post时测试阻塞无法结束问题

解决Mockk模拟Ktor HttpClient.post时测试阻塞的问题

你遇到的测试阻塞问题,核心原因是对HttpClient.post的lambda参数匹配错误。你手动mock了HttpRequestBuilder.() -> Unit类型的mockFunc,但实际业务代码中传入的是真实的lambda,和你mock的实例完全不匹配,导致coEvery的存根逻辑从未触发,测试一直挂起等待响应。

修改后的测试代码

@Test
fun `submit report`() = runTest {
    val mockHttpClient: HttpClient = mockk()
    val mockResponse: HttpResponse = mockk(relaxed = true)

    // 存根响应状态
    coEvery { mockResponse.status } returns HttpStatusCode.OK
    // 存根body方法,匹配目标泛型类型
    coEvery { 
        mockResponse.body<HandlingResponse.Success>() 
    } returns HandlingResponse.Success()

    // 关键:用any()匹配任意lambda参数,而非手动mock的lambda实例
    coEvery { 
        mockHttpClient.post(any<String>(), any<HttpRequestBuilder.() -> Unit>()) 
    } returns mockResponse

    val client = HandlingReportClient(mockHttpClient)
    val result = client.submitReport(report)
    
    // 断言结果正确性
    check(result is HandlingResponse.Success)
    assertEquals("OK", result.toString())
}

额外优化:验证lambda参数行为

如果需要验证业务代码中对HttpRequestBuilder的配置逻辑(比如设置请求体、headers等),可以用capturingSlot捕获lambda参数,执行后做断言:

@Test
fun `submit report with request verification`() = runTest {
    val mockHttpClient: HttpClient = mockk()
    val mockResponse: HttpResponse = mockk(relaxed = true)
    val requestBuilderSlot = slot<HttpRequestBuilder.() -> Unit>()

    coEvery { mockResponse.status } returns HttpStatusCode.OK
    coEvery { mockResponse.body<HandlingResponse.Success>() } returns HandlingResponse.Success()

    // 捕获传入的lambda参数
    coEvery { 
        mockHttpClient.post(any<String>(), capture(requestBuilderSlot)) 
    } returns mockResponse

    val client = HandlingReportClient(mockHttpClient)
    val result = client.submitReport(report)
    
    // 执行捕获的lambda,验证请求构建逻辑
    val builder = HttpRequestBuilder()
    requestBuilderSlot.captured.invoke(builder)
    // 示例:验证请求方法为POST
    assertEquals(HttpMethod.Post, builder.method)
    // 可添加更多断言,比如检查请求body、headers等

    check(result is HandlingResponse.Success)
    assertEquals("OK", result.toString())
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:12:13