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

Spring Boot JUnit5中Mock外部API并自定义响应的问题

解决Spring Boot集成测试中WireMock Mock第三方API失效的问题

核心问题分析

你的代码存在几个关键错误,导致Stub配置不生效:

  • 试图让WireMock绑定到第三方API的1.2.3.4:1111:本地通常无法绑定非本机IP,且完全没必要——我们不需要替代第三方的网络地址,只需让微服务把请求发到本地WireMock服务即可。
  • wireMockServer.configureFor("1.2.3.4", 1111)用法错误:该方法用于指定WireMock客户端连接的服务地址,而你的WireMock是本地动态端口启动的,应指向它自身的地址和端口。
  • Stub中的urlEqualTo("https://1.2.3.4:1111/aaa/unit")不符合规则:urlEqualTo只需匹配请求路径部分(即/aaa/unit),无需完整URL前缀。

正确解决方案

1. 动态替换第三方API地址

通过@DynamicPropertySource在测试启动时,将微服务中第三方API的配置值替换为WireMock的实际地址,让RestTemplate自动把请求发到WireMock。

2. 修正WireMock Stub配置

仅针对请求路径和参数设置Stub,不需要完整URL。

修正后的完整测试代码

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ActiveProfiles("test")
class ApplicationIntegrationTest {

    @LocalServerPort
    int randomServerPort;
    @Autowired
    private WebTestClient webTestClient;

    private static WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort());

    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        // 假设你的微服务用third-party.api.url配置第三方API地址
        registry.add("third-party.api.url", () -> wireMockServer.baseUrl());
    }

    @BeforeAll
    void init() {
        wireMockServer.start();
        // 配置WireMock使用自身端口(可选,默认就是本地地址)
        WireMock.configureFor(wireMockServer.port());
    }

    @AfterAll
    void tearDown() {
        wireMockServer.stop();
    }

    @Test
    void searchShelf() throws Exception {
        // 正确的Stub配置:仅匹配路径和查询参数
        wireMockServer.stubFor(WireMock.get(urlEqualTo("/aaa/unit"))
                .withQueryParam("name", equalTo("ABCD"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody("[]")));

        this.webTestClient.get()
                .uri(uriBuilder -> uriBuilder.path("/unitmgmt/unit")
                        .queryParam("name", "ABCD")
                        .build())
                .exchange()
                .expectStatus()
                .is2xxSuccessful();
    }
}

关键说明

  • 确保你的微服务中,第三方API地址是从配置文件读取(如third-party.api.url),而非硬编码在代码里,这样才能在测试时动态替换。
  • wireMockServer.baseUrl()会返回WireMock的完整地址(如http://localhost:xxxx),加上路径/aaa/unit就是RestTemplate的调用目标。
  • 如果之前硬编码了第三方API地址,需先重构为从配置读取,这是保证可测试性的基础要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:44:57