1. 概述

MockServer 是一个用于模拟/存根外部 HTTP API 的工具。在微服务架构和分布式系统中,它特别有用,能帮我们解决依赖服务不可用或测试环境不稳定的问题。

核心功能包括: ✅ 生成固定响应 ✅ 转发请求到其他服务器 ✅ 执行回调逻辑 ✅ 验证请求是否符合预期

2. Maven 依赖

要在项目中使用 MockServer,需要添加两个依赖:

<dependency>
    <groupId>org.mock-server</groupId>
    <artifactId>mockserver-netty</artifactId>
    <version>3.10.8</version>
</dependency>
<dependency>
    <groupId>org.mock-server</groupId>
    <artifactId>mockserver-client-java</artifactId>
    <version>3.10.8</version>
</dependency>

最新版本可在 Maven 中央仓库 查询

3. MockServer 核心功能

简单粗暴地说,它能干这些事:

  • 生成固定响应:直接返回预设的响应数据
  • 请求转发:将请求原样转发到其他服务器
  • 执行回调:触发自定义逻辑处理请求
  • 请求验证:检查被测系统是否发送了符合预期的请求

4. 启动 MockServer

有几种方式可以启动服务器,我们来看看最常用的两种:

4.1. 通过 Maven 插件启动

process-test-class 阶段启动,verify 阶段停止:

<plugin>
    <groupId>org.mock-server</groupId>
    <artifactId>mockserver-maven-plugin</artifactId>
    <version>3.10.8</version>
    <configuration>
        <serverPort>1080</serverPort>
        <proxyPort>1090</proxyPort>
        <logLevel>DEBUG</logLevel>
        <initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>
    </configuration>
    <executions>
        <execution>
            <id>process-test-classes</id>
            <phase>process-test-classes</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>verify</id>
            <phase>verify</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>

4.2. 通过 Java API 启动

使用 startClientAndServer() API 启动服务器。通常在测试类中这样处理:

public class TestMockServer {

    private ClientAndServer mockServer;

    @BeforeClass
    public void startServer() {
        mockServer = startClientAndServer(1080);
    }
 
    @AfterClass 
    public void stopServer() { 
        mockServer.stop();
    }
 
    // ...
}

5. 模拟客户端

MockServerClient API 用于连接 MockServer,它定义了请求和响应的交互模型。主要支持以下操作:

5.1. 创建带模拟响应的期望

期望(Expectation)是 MockServer 的核心概念,用于定义“当收到XX请求时,返回YY响应”。

创建期望需要定义两部分:

  1. 请求匹配器:匹配请求的条件
  2. 响应动作:返回的响应内容

请求匹配条件包括:

  • path – URL 路径
  • query string – URL 参数
  • headers – 请求头
  • cookies – 客户端 Cookie
  • body – POST 请求体(支持 XPATH、JSON、正则表达式等匹配方式)

响应动作包含:

  • status codes – HTTP 状态码(如 200、400)
  • body – 响应体(任意字节数据)
  • headers – 响应头
  • cookies – 响应 Cookie

创建期望示例:

public class TestMockServer {
    private void createExpectationForInvalidAuth() {
        new MockServerClient("127.0.0.1", 1080)
          .when(
            request()
              .withMethod("POST")
              .withPath("/validate")
              .withHeader("\"Content-type\", \"application/json\"")
              .withBody(exact("{username: 'foo', password: 'bar'}")),
              exactly(1))
                .respond(
                  response()
                    .withStatusCode(401)
                    .withHeaders(
                      new Header("Content-Type", "application/json; charset=utf-8"),
                      new Header("Cache-Control", "public, max-age=86400"))
                    .withBody("{ message: 'incorrect username and password combination' }")
                    .withDelay(TimeUnit.SECONDS,1)
                );
    }
    // ...
}

这里我们模拟了一个 POST 请求:

  • 使用 exactly(1) 指定只匹配一次
  • 返回 401 状态码
  • 设置响应头和响应体
  • 添加 1 秒延迟(模拟真实网络延迟)

5.2. 转发请求

可以将请求转发到其他服务器,转发动作可配置:

  • host – 目标主机(如 www.example.com)
  • port – 目标端口(默认 80)
  • scheme – 协议(HTTP 或 HTTPS)

转发示例:

private void createExpectationForForward(){
    new MockServerClient("127.0.0.1", 1080)
      .when(
        request()
          .withMethod("GET")
          .withPath("/index.html"),
          exactly(1))
        .forward(
          forward()
            .withHost("www.mock-server.com")
            .withPort(80)
            .withScheme(HttpForward.Scheme.HTTP)
           );
}

⚠️ 注意:外层 forward() 指定转发动作,内层 forward() 构建目标 URL

5.3. 执行回调

当收到特定请求时,可以触发自定义回调逻辑。回调类需实现 org.mockserver.mock.action.ExpectationCallback 接口,且:

  • 必须有默认构造函数
  • 必须在类路径中

回调示例:

private void createExpectationForCallBack() {
    mockServer
      .when(
        request().withPath("/callback"))
        .callback(
          callback()
            .withCallbackClass("com.baeldung.mock.server.TestExpectationCallback")
        );
}

当收到 /callback 请求时,会执行指定类的 handle 方法:

public class TestExpectationCallback implements ExpectationCallback {

    public HttpResponse handle(HttpRequest httpRequest) {
        if (httpRequest.getPath().getValue().endsWith("/callback")) {
            return httpResponse;
        } else {
            return notFoundResponse();
        }
    }

    public static HttpResponse httpResponse = response()
      .withStatusCode(200);
}

5.4. 验证请求

MockServerClient 可以验证被测系统是否发送了符合预期的请求:

private void verifyPostRequest() {
    new MockServerClient("localhost", 1080).verify(
      request()
        .withMethod("POST")
        .withPath("/validate")
        .withBody(exact("{username: 'foo', password: 'bar'}")),
        VerificationTimes.exactly(1)
    );
}

使用 VerificationTimes 指定请求匹配次数(如 exactly(1) 表示必须且仅匹配一次)。

6. 总结

本文介绍了 MockServer 的核心功能和使用方式:

  • 通过 Maven 插件或 Java API 启动服务器
  • 创建期望模拟响应
  • 转发请求到其他服务
  • 执行自定义回调逻辑
  • 验证请求是否符合预期

在测试复杂系统时,MockServer 能有效隔离外部依赖,提高测试稳定性和效率。完整代码示例可在 GitHub 获取。


原始标题:Introduction to MockServer | Baeldung