如何用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
相关产品推荐
相关产品推荐

