关于 unit-test-wiremock-rest-api
面向测试外部 REST API 集成的 WireMock 技能指南,介绍如何隔离网络依赖并验证客户端行为。涵盖响应桩、请求校验及超时和错误场景。
主要功能
- 01使用 WireMock 模拟 HTTP 响应
- 02匹配 URL、请求头和请求体
- 03验证客户端发出的请求
- 04覆盖超时与错误响应
- 05使用动态端口避免冲突
适用场景
- 01测试调用第三方 REST API 的服务
- 02模拟 4xx、5xx 和超时情况
- 03校验请求参数、请求头及请求体
- 04并行运行隔离网络的测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill unit-test-wiremock-rest-api安装后在 Claude Code 中输入/unit-test-wiremock-rest-api确认已加载。
附带文件references/advanced-examples.md
详细介绍
使用 WireMock 测试 REST API
概述
使用 WireMock 测试外部 REST API 集成的模式:桩响应、验证请求、测试错误场景,以及无需网络依赖的快速测试。
适用场景
- 测试调用外部 REST API 的服务
- 为 HTTP 响应设置桩,以便获得可预测的测试行为
- 测试错误场景(超时、5xx 错误、格式错误的响应)
- 验证请求详情(标头、查询参数、请求正文)
操作说明
- 添加依赖项:在测试作用域中添加 WireMock(Maven/Gradle)
- 注册扩展:使用
@RegisterExtension WireMockExtension和dynamicPort() - 配置客户端:使用
wireMock.getRuntimeInfo().getHttpBaseUrl()作为基础 URL - 设置响应桩:使用
stubFor()并匹配请求(URL、标头、正文) - 执行并断言:调用服务方法,使用 AssertJ 验证结果
- 验证请求:使用
verify()确保 API 使用正确
如果桩未匹配:检查 URL 编码和标头名称;查询参数使用 urlEqualTo。
如果测试挂起:在 HTTP 客户端中配置连接超时;使用 withFixedDelay() 模拟超时。
如果端口冲突:始终使用 wireMockConfig().dynamicPort()。
示例
Maven 依赖项
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
基本桩设置与验证
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.assertj.core.api.Assertions.assertThat;
class ExternalWeatherServiceTest {
@RegisterExtension
static WireMockExtension wireMock = WireMockExtension.newInstance()
.options(wireMockConfig().dynamicPort())
.build();
@Test
void shouldFetchWeatherDataFromExternalApi() {
wireMock.stubFor(get(urlEqualTo("/weather?city=London"))
.withHeader("Accept", containing("application/json"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"city\":\"London\",\"temperature\":15,\"condition\":\"Cloudy\"}")));
String baseUrl = wireMock.getRuntimeInfo().getHttpBaseUrl();
WeatherApiClient client = new WeatherApiClient(baseUrl);
WeatherData weather = client.getWeather("London");
assertThat(weather.getCity()).isEqualTo("London");
assertThat(weather.getTemperature()).isEqualTo(15);
wireMock.verify(getRequestedFor(urlEqualTo("/weather?city=London"))
.withHeader("Accept", containing("application/json")));
}
}
错误场景、正文验证、超时模拟和有状态测试请参见 references/advanced-examples.md。
最佳实践
- 动态端口:避免并行执行测试时发生冲突
- 验证请求:确保客户端正确使用 API
- 测试错误:覆盖超时、4xx 和 5xx 场景
- 专注的桩:每个测试只关注一个问题
- 自动重置:
@RegisterExtension会在测试之间重置 WireMock - 切勿调用真实 API:始终为第三方端点设置桩
限制和警告
- 必须使用动态端口:固定端口会导致并行执行冲突
- HTTPS 测试:测试 TLS 连接时配置 WireMock TLS 设置
- 桩优先级:更具体的桩优先于通用桩
- 性能:WireMock 会增加开销;在客户端层进行模拟可加快测试
- API 变更:确保桩与实际 API 契约保持同步
参考资料
- WireMock 文档
- WireMock 桩设置指南
references/advanced-examples.md- 错误场景、正文验证、超时
评论
支持 Markdown