如何实现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
相关产品推荐
相关产品推荐

