WireMock 是一个强大的服务虚拟化工具,能模拟出各种 HTTP API,在没有真实后端服务的情况下,也能完成开发和测试。
一、解决什么问题?
在做测试或前端开发时,经常会遇到这些情况:
后端接口还没开发好,前端只能等待。
想测试边界情况(如超时、返回500错误),但真实服务很难模拟。
依赖的第三方服务不稳定或调用有成本。
WireMock 就是一个替身演员建立一个假的 HTTP 服务,根据设置的规则来响应请求。告诉它收到什么请求时返回什么响应,它就能精确地模拟出各种服务的行为。
二、启动两种途径
独立运行方式
最简单的上手方式,把 WireMock 作为一个独立的进程运行。
去 WireMock 官网下载最新的独立 JAR 包。
在终端执行: java -jar wiremock-standalone-版本号.jar
会立即启动一个监听在 http://localhost:8080 的模拟服务器。现在就可以直接通过它的管理 API 来设置模拟规则了。
嵌入式方式
这是将它集成到你的 Java 自动化测试中的方式。
在项目中添加依赖(以 Maven 为例):
xml
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>3.5.2</version> <!-- 请使用最新版 -->
<scope>test</scope>
</dependency>
在测试代码里启动 new WireMockServer() 即可。
三、快速设置一个Mock API
WireMock的重点是 Stub(桩)。一条桩规则定义了请求一致条件和响应内容。
模拟一个最简单的用户查询接口,当通过 GET /api/users/1 请求时,返回用户ID为1的信息。
可以通过以下方式来设置这个桩:
通过RESTful管理API创建
向 http://localhost:8080/__admin/mappings 发送一个 POST 请求,身体内容为:
json
{
"request": {
"method": "GET",
"url": "/api/users/1"
},
"response": {
"status": 200,
"jsonBody": {
"id": 1,
"name": "新手的第一个Mock",
"email": "test@example.com"
},
"headers": {
"Content-Type": "application/json"
}
}
}
可以用 Postman 或 curl 发送这个请求。之后,在浏览器访问 http://localhost:8080/api/users/1,就会得到预期的 JSON 响应。
通过Java代码创建
java
WireMockServer wireMockServer = new WireMockServer();
wireMockServer.start();
// 配置桩
wireMockServer.stubFor(get(urlEqualTo("/api/users/1"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"id\": 1, \"name\": \"新手的第一个Mock\"}")));
// 现在可以像访问真实服务一样,访问 wireMockServer.baseUrl() + "/api/users/1"
四、真实测试场景
只有简单的成功响应是不够的,实际测试中需要模拟各种异常和复杂行为。
模拟故障和延迟
java
// 模拟一个5秒后才返回的慢接口
stubFor(get(urlPathMatching("/api/slow"))
.willReturn(aResponse()
.withStatus(200)
.withFixedDelay(5000))); // 延迟5000毫秒
// 模拟一个返回503 Service Unavailable的错误
stubFor(post(urlEqualTo("/api/order"))
.willReturn(aResponse()
.withStatus(503)
.withStatusMessage("Service Unavailable")));
灵活的请求一致
不要只一致死的URL,学会使用优先级、正则表达式和高级一致。
java
// 使用正则,一致所有 /api/users/ 后面跟数字的GET请求
stubFor(get(urlPathMatching("/api/users/\\d+"))
.willReturn(aResponse().withStatus(200)));
// 根据请求体一致,同一个URL根据内容返回不同响应
stubFor(post(urlEqualTo("/api/login"))
.withRequestBody(matchingJsonPath("$.username", equalTo("admin")))
.willReturn(aResponse().withStatus(200).withBody("Admin Login Success")));
证实
测试的目的是让被测代码获取正确响应,还要证实确实发送了正确的请求。
java
// 证实被测代码是不是向“/api/notify”发送过1次POST请求,且请求体包含“成功”
verify(postRequestedFor(urlEqualTo("/api/notify"))
.withRequestBody(containing("成功")));
// 证实某个请求一次都没有发生
verify(0, getRequestedFor(urlEqualTo("/api/secret")));
录制和回放
如果已经有一个可用的真实服务,可以用 WireMock 把操作录制下来作为桩。
在启动 WireMock 时使用代理方式。
访问 WireMock 的端口,并配置它把请求转发到真实服务。
执行操作后,WireMock 会自动创建对应的桩文件。下次测试时,就可以断开真实服务,用录制好的桩直接回放。