You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mockito Stub HttpClient的send方法并返回预期响应?

如何Mock HttpClient的send方法返回预期JSON响应

核心思路

要Mock HttpClient.send() 方法并返回自定义JSON响应,需借助Mockito完成Mock对象的创建与Stub配置,同时优先通过依赖注入重构业务代码,让HttpClient可被替换为Mock实例(避免直接在方法内new HttpClient导致无法Mock)。


步骤1:重构业务代码(关键)

将HttpClient通过构造方法注入到业务类中,而非在方法内直接实例化:

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse.BodyHandlers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ApiService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ApiService.class);
    private final HttpClient httpClient;

    // 构造方法注入HttpClient,方便测试时替换为Mock对象
    public ApiService(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public String callExternalApi(String requestBody, String authorizationHeader) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:8080/api"))
                .POST(BodyPublishers.ofString(requestBody))
                .header("Authorization", authorizationHeader)
                .header("Content-Type", "application/json")
                .build();

        HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
        LOGGER.debug(response.body());
        return response.body();
    }
}

步骤2:编写JUnit5测试用例(结合Mockito)

通过Mockito创建Mock的HttpClient和HttpResponse,Stub send() 方法返回预期的JSON响应:

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.junit.jupiter.api.Test;

public class ApiServiceTest {

    @Test
    void testCallExternalApi_ReturnsExpectedJson() throws Exception {
        // 1. 创建Mock的HttpClient实例
        HttpClient mockHttpClient = mock(HttpClient.class);

        // 2. 准备预期的API响应JSON
        String expectedJsonResponse = "{\"id\": 1, \"name\": \"测试实体\", \"status\": \"success\"}";

        // 3. Mock HttpResponse对象,配置返回的body和状态码
        HttpResponse<String> mockResponse = mock(HttpResponse.class);
        when(mockResponse.body()).thenReturn(expectedJsonResponse);
        when(mockResponse.statusCode()).thenReturn(200); // 可选:模拟成功状态码

        // 4. Stub HttpClient的send方法,指定返回Mock的HttpResponse
        when(mockHttpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class)))
                .thenReturn(mockResponse);

        // 5. 初始化业务类,传入Mock的HttpClient
        ApiService apiService = new ApiService(mockHttpClient);

        // 6. 执行测试方法
        String actualResponse = apiService.callExternalApi("{\"param\": \"test\"}", "Bearer auth-token");

        // 7. 验证结果是否符合预期
        assert actualResponse.equals(expectedJsonResponse);
        // 可选:验证send方法是否被正确调用
        verify(mockHttpClient).send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class));
    }
}

关键说明

  • 依赖注入的必要性:如果业务代码中直接使用HttpClient.newHttpClient()创建实例,会导致无法替换为Mock对象,因此必须重构为依赖注入形式(构造方法/Setter注入均可)。
  • Stub的灵活性:可以根据测试场景,修改mockResponse的配置,比如返回404状态码、错误JSON等,模拟不同的API响应情况。
  • 参数匹配:示例中使用any()匹配任意HttpRequest和BodyHandler,若需要更精确的匹配(比如验证请求URL、Header是否正确),可以替换为argThat()自定义匹配逻辑。

内容的提问来源于stack exchange,提问作者BSM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:57:42