拓展阅读
jmockit-01-test 之 jmockit 入门使用案例
mockito-01-overview mockito 简介及入门使用
wiremock
WireMock是一个流行的开源工具,用于API模拟测试,每月下载量超过500万次。它可以帮助您创建稳定的测试和开发环境,隔离与不稳定的第三方服务的依赖,并模拟尚不存在的API。
WireMock于2011年由Tom Akehurst作为Java库启动,现在已经涵盖多种编程语言和技术栈。
它可以作为库或客户端包装器在许多语言中运行,也可以作为独立的服务器运行。项目及其生态系统背后有一个庞大的社区。
WireMock支持多种创建模拟API的方法 - 在代码中、通过其REST API、作为JSON文件以及通过记录代理到另一个目标的HTTP流量。
WireMock具有丰富的匹配系统,允许将传入请求的任何部分与复杂和精确的条件进行匹配。
通过基于Handlebars的模板系统,可以动态生成任何复杂度的响应。
最后,由于其众多的扩展点和全面的API,WireMock易于集成到任何工作流程中。
关键特性
WireMock可以在单元测试中运行,也可以作为独立进程或容器运行。
其关键特性包括:
- 可通过URL、头部和正文内容模式进行HTTP响应存根匹配
- 支持通过流畅的Java API、JSON文件和HTTP传输的JSON进行配置
- 存根的录制和回放
- 请求验证
- 故障和响应延迟注入
- 按请求的条件代理
- 用于请求检查和替换的浏览器代理
- 具有状态的行为模拟
- 可扩展性
WireMock生态系统
WireMock具有针对其他语言和测试框架的实现和适配器。它支持多种技术栈的适配器和实现,包括Python、.NET、Golang和Rust。
对于JVM生态系统,有适用于Spring Boot、Quarkus、Kotlin、Testcontainers等的库。
WireMock还可以在Android支持上运行,并即将提供官方的gRPC和GraphQL适配器。
快速入门:使用Java和JUnit 4进行API模拟
在本指南中,我们将使用WireMock和JUnit 4编写API单元测试。
先决条件
- Java 11或17
- Maven或Gradle,使用最新版本
- 一个基于Maven和Gradle的Java项目
- 一个我们将用作演练场的单元测试文件
将WireMock依赖项添加到您的项目
WireMock通过Maven Central分发,可以通过常见的构建工具的依赖管理包含在您的项目中。
要将标准的WireMock JAR添加为项目依赖项,请将以下依赖项放在构建文件的dependencies部分中。
在我们的测试中,我们还将使用AssertJ来验证响应。为了发送请求,我们将使用Java 11+中可用的嵌入式HTTP客户端。
如果您想添加一个Java 1.8测试,您将需要添加一个外部的HTTP客户端实现,如Apache HttpClient。
xml
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>3.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
添加WireMock规则
WireMock提供了一些JUnit规则来管理服务器的生命周期和设置/拆卸任务。
要使用WireMock的流畅API,请添加以下导入语句:
java
import static com.github.tomakehurst.wiremock.client.WireMock.*;
为了在每个测试用例中自动启动和停止WireMock,请将以下内容添加到您的测试类(或其超类):
java
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089); // No-args constructor defaults to port 8080
写一个测试
java
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
...
@Test
public void exampleTest() {
// Setup the WireMock mapping stub for the test
stubFor(post("/my/resource")
.withHeader("Content-Type", containing("xml"))
.willReturn(ok()
.withHeader("Content-Type", "text/xml")
.withBody("<response>SUCCESS</response>")));
// Setup HTTP POST request (with HTTP Client embedded in Java 11+)
final HttpClient client = HttpClient.newBuilder().build();
final HttpRequest request = HttpRequest.newBuilder()
.uri(wiremockServer.getRequestURI("/my/resource"))
.header("Content-Type", "text/xml")
.POST().build();
// Send the request and receive the response
final HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
// Verify the response (with AssertJ)
assertThat(response.statusCode()).as("Wrong response status code").isEqualTo(200);
assertThat(response.body()).as("Wrong response body").contains("<response>SUCCESS</response>");
}
拓展测试类
为了对由规则创建的WireMock服务器的设置有更多的控制,您可以将通过流式构建的Options对象传递给规则的构造函数。
让我们以更改端口号为例:
java
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
...
@Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8089).httpsPort(8443));
您可以让WireMock(更准确地说是JVM)选择随机的、空闲的HTTP和HTTPS端口。如果您想要并发运行测试,这是一个很好的选择。
java
@Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());
可以用下面的发现对应的端口信息:
java
int port = wireMockRule.port();
int httpsPort = wireMockRule.httpsPort();
wiremock 是如何实现 http 服务的模拟的?原理是什么
WireMock实现HTTP服务的模拟的基本原理是拦截和模拟HTTP请求,并根据预定义的规则返回相应的模拟响应。
以下是WireMock的基本原理:
-
代理模式: WireMock 可以作为一个代理服务器,拦截客户端发出的HTTP请求。当 WireMock 作为代理运行时,它会监听指定的端口,并将接收到的请求发送到实际的目标服务器。WireMock 在中间拦截这些请求,允许你模拟响应。
-
Stubbing: 在 WireMock 中,模拟服务的期望行为通过 stub(存根)来定义。一个 stub 定义了一个匹配规则和一个对应的响应。当收到符合匹配规则的请求时,WireMock 将返回预定义的响应,而不是将请求转发到实际的目标服务器。
-
匹配规则: WireMock 提供了丰富的匹配规则,可以根据请求的URL、HTTP方法、请求体、查询参数等条件进行匹配。这使得可以精确地定义哪些请求应该由 WireMock 进行模拟响应。
-
DSL(领域特定语言): WireMock 使用了DSL,即一种特定于领域的语言,用于定义 stubs。DSL 提供了清晰而简洁的语法,使得创建和配置 stubs 变得直观和易读。
-
内嵌服务器: 除了代理模式,WireMock 还可以作为一个独立的HTTP服务器运行。在这种情况下,它监听指定的端口并直接处理客户端发出的请求,而不需要实际的目标服务器。
-
录制和回放: WireMock 具有录制和回放功能,可以用于记录实际服务的请求和响应,然后将其用作模拟服务的期望行为。这有助于创建与实际服务行为一致的 stubs。