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
相关产品推荐
相关产品推荐

