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

如何实现WireMock端口动态化避免占用?测试中如何获取端口配置端点

当然可以实现!

完全没问题,WireMock结合Spring(从你提到的@AutoConfigureWireMock来看,应该是用Spring生态)提供了非常便捷的方式来实现动态端口,彻底解决端口被占用的问题,同时自动同步服务的github.api.endpoint配置。下面是两种最常用的实现方案:

方案一:用Spring Boot的@DynamicPropertySource(推荐,Spring Boot 2.2+)

这是最简洁的方式,利用Spring的动态属性源机制,在测试启动时自动获取WireMock的随机端口并覆盖配置:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.context.DynamicPropertyRegistry;
import com.github.tomakehurst.wiremock.WireMockServer;

@SpringBootTest
@AutoConfigureWireMock(port = 0) // 传入0表示让WireMock随机选可用端口
public class GitHubServiceIntegrationTest {

    // 动态覆盖配置属性
    @DynamicPropertySource
    static void setupGitHubApiEndpoint(DynamicPropertyRegistry registry) {
        // 获取WireMock实际使用的端口
        int wireMockPort = WireMockServer.getInstance().port();
        // 动态设置服务的GitHub API端点
        registry.add("github.api.endpoint", () -> "http://localhost:" + wireMockPort);
    }

    @Test
    void testMalformedResponseHandling() {
        // 配置WireMock返回格式错误的响应
        stubFor(get(urlEqualTo("/api/users/niemar"))
                .willReturn(aResponse()
                        .withStatus(400)
                        .withHeader("Content-Type", "application/json")
                        .withBody("{\"error\": \"Invalid JSON format\"}")));
        
        // 调用你的自有服务,验证它对格式错误的处理逻辑
        // 比如:yourGitHubClient.getUser("niemar") 然后断言错误处理行为
    }

    @Test
    void testTimeoutScenario() {
        // 模拟超时场景:设置超长响应延迟
        stubFor(get(urlEqualTo("/api/repos/niemar/my-project"))
                .willReturn(aResponse()
                        .withFixedDelay(15000) // 15秒延迟,触发服务的超时逻辑
                        .withStatus(200)));
        
        // 调用服务并验证超时处理
    }
}

关键说明:

  • @AutoConfigureWireMock(port = 0):告诉WireMock不要固定端口,随机选择一个当前系统可用的端口。
  • DynamicPropertyRegistry:Spring提供的用于动态注册/覆盖配置属性的工具,这里直接把github.api.endpoint指向WireMock的动态端口,你的服务通过@Value("${github.api.endpoint}")就能拿到最新的地址。

方案二:JUnit 4 或非Spring Boot场景的手动配置

如果是用JUnit 4或者没有使用Spring Boot的@DynamicPropertySource,可以通过WireMock的API手动获取端口并更新配置:

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.github.tomakehurst.wiremock.core.WireMockSpring;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.test.context.TestPropertySource;

// 先占位端口变量,后续动态替换
@TestPropertySource(properties = {"github.api.endpoint=http://localhost:${wiremock.port}"})
public class GitHubServiceJUnit4Test {

    // 初始化WireMock为动态端口模式
    @Rule
    public WireMockRule wireMockRule = new WireMockRule(WireMockSpring.options().dynamicPort());

    @Test
    void testErrorResponses() {
        // 获取WireMock实际使用的端口
        int actualPort = wireMockRule.port();
        
        // 手动更新系统属性(如果你的服务读取系统属性的话)
        System.setProperty("github.api.endpoint", "http://localhost:" + actualPort);

        // 配置WireMock的stub逻辑
        stubFor(post(urlEqualTo("/api/repos"))
                .willReturn(aResponse()
                        .withStatus(500)
                        .withBody("Internal Server Error")));
        
        // 调用服务并验证处理逻辑
    }
}

注意事项:

  • 确保你的服务是通过配置属性(而不是硬编码)读取github.api.endpoint的,这样动态更新的配置才能生效。
  • 使用@AutoConfigureWireMock时,Spring会自动管理WireMock服务器的启动和停止,不用手动处理生命周期。
  • 动态端口模式下,每次测试运行的端口都不一样,完全避免了端口被其他进程占用的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:30:50