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

WireMock调用超时问题:如何确保Stub就绪后再执行测试?

确保WireMock Stub就绪后执行HTTP调用的解决方案

你遇到的这个超时问题很典型——虽然stubFor()是同步调用,但在Spring Boot集成测试+协程的场景下,偶尔会出现实际服务调用比WireMock Stub完全就绪要快的情况,导致请求超时。下面给你几个经过验证的解决方案:

方法一:主动验证Stub可用性(最可靠)

注册Stub之后,先发送一个测试请求到WireMock,并用verify()方法等待这个请求被处理,以此确认Stub已经生效:

@Test
fun `without travel ads returns sorted organic properties`() {
    // 1. 注册你的Stub
    stubFor(post(urlEqualTo("/myApi"))
            .willReturn(aResponse()
                    .withHeader("Content-Type", "application/x-protobuf")
                    .withBody(stubResponse.toByteArray())))

    // 2. 先发送一个测试请求到WireMock,验证Stub能响应
    val testClient = HttpClient.newHttpClient()
    val testRequest = HttpRequest.newBuilder()
            .uri(URI.create("http://localhost:${wireMockServer.port()}/myApi"))
            .POST(HttpRequest.BodyPublishers.ofByteArray(byteArrayOf()))
            .build()
    testClient.send(testRequest, HttpResponse.BodyHandlers.discarding())

    // 3. 等待测试请求被命中(设置5秒超时,足够Stub就绪)
    verify(times(1), within(5000), postRequestedFor(urlEqualTo("/myApi")))

    // 4. 现在再执行实际的服务调用
    val actualResponse = runBlocking { myService.getUserData() }

    // 你的断言逻辑
    <<<<部分断言>>>>
}

注意:要使用这个方法,你需要在BaseIT类里注入WireMockServer实例:

@Autowired
lateinit var wireMockServer: WireMockServer

方法二:用WireMock的waitFor API等待Stub状态

WireMockServer提供了waitFor()方法,可以自定义等待条件,比如检查我们注册的Stub是否已经存在于WireMock的映射列表中:

@Test
fun `without travel ads returns sorted organic properties`() {
    // 注册Stub时保存它的ID
    val stubId = stubFor(post(urlEqualTo("/myApi"))
            .willReturn(aResponse()
                    .withHeader("Content-Type", "application/x-protobuf")
                    .withBody(stubResponse.toByteArray())))

    // 等待Stub就绪,最多等5秒
    wireMockServer.waitFor(5000) {
        wireMockServer.stubMappings().any { it.id == stubId }
    }

    // 执行实际调用
    val actualResponse = runBlocking { myService.getUserData() }

    // 断言部分
    <<<<部分断言>>>>
}

方法三:优化协程执行时序

因为你用了runBlocking执行协程调用,可能存在协程调度比Stub注册生效快的情况。可以试试切换到IO调度器,或者添加一个微小的延迟(应急可用):

@Test
fun `without travel ads returns sorted organic properties`() {
    stubFor(post(urlEqualTo("/myApi"))
            .willReturn(aResponse()
                    .withHeader("Content-Type", "application/x-protobuf")
                    .withBody(stubResponse.toByteArray())))

    // 切换到IO调度器,给Stub足够的生效时间
    val actualResponse = runBlocking(Dispatchers.IO) {
        delay(100) // 可选:添加100ms延迟,确保Stub完全就绪
        myService.getUserData()
    }

    // 断言部分
    <<<<部分断言>>>>
}

方法四:全局配置WireMock超时

如果不想在每个测试里加验证逻辑,也可以在application-dev.properties里全局设置WireMock的超时时间,给Stub足够的就绪窗口:

# 设置WireMock的请求和响应超时为10秒
wiremock.server.request-timeout=10000
wiremock.server.response-timeout=10000

总结

优先推荐方法一和方法二,它们是主动验证Stub就绪的方式,比单纯延长超时更可靠;方法三适合协程场景下的快速调整;方法四作为全局兜底配置使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:07:41