如何Mock Apache HttpClient 5.x中的CloseableHttpResponse?
解决Apache HttpClient 5.x中CloseableHttpResponse的测试实例化问题
针对你遇到的CloseableHttpResponse无法直接实例化(且不想依赖Mockito final mock机制)的问题,有两个更规范、简便的方案:
方案一:使用官方测试工具类
Apache HttpClient 5.x专门提供了测试专用的工具类CloseableHttpResponses(位于org.apache.hc.client5.testing包下),可以直接生成符合要求的CloseableHttpResponse实例,完全官方支持,无mock风险。
操作步骤:
- 先在测试依赖中引入
httpclient5-testing模块:
<dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5-testing</artifactId> <version>你的HttpClient 5.x版本号</version> <scope>test</scope> </dependency>
- 在测试代码中直接调用静态方法生成响应:
// 生成200 OK的空响应 CloseableHttpResponse okResponse = CloseableHttpResponses.create(HttpStatus.SC_OK); // 生成带JSON响应实体的200响应 String responseBody = "{\"data\": \"test\"}"; HttpEntity entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON); CloseableHttpResponse responseWithBody = CloseableHttpResponses.create(HttpStatus.SC_OK, entity);
方案二:手动实现CloseableHttpResponse接口
由于CloseableHttpResponse本质是接口,你可以编写极简实现类,只覆盖测试需要用到的方法,其他方法留空或抛出不支持异常即可,完全可控且无额外依赖。
示例实现:
import org.apache.hc.core5.http.*; import org.apache.hc.core5.http.io.entity.HttpEntity; import java.io.Closeable; import java.io.IOException; public class MockHttpResponse implements CloseableHttpResponse { private final int statusCode; private final HttpEntity entity; public MockHttpResponse(int statusCode, HttpEntity entity) { this.statusCode = statusCode; this.entity = entity; } @Override public StatusLine getStatusLine() { return new BasicStatusLine(HttpVersion.HTTP_1_1, statusCode, "Success"); } @Override public HttpEntity getEntity() { return entity; } @Override public void close() throws IOException { // 测试环境无需实际关闭资源,空实现即可 } // 以下为其他接口方法的极简实现,按需调整 @Override public ProtocolVersion getProtocolVersion() { return HttpVersion.HTTP_1_1; } @Override public boolean containsHeader(String name) { return false; } @Override public Header[] getHeaders(String name) { return new Header[0]; } @Override public Header getFirstHeader(String name) { return null; } @Override public Header getLastHeader(String name) { return null; } @Override public Header[] getAllHeaders() { return new Header[0]; } @Override public void addHeader(Header header) {} @Override public void addHeader(String name, String value) {} @Override public void setHeader(Header header) {} @Override public void setHeader(String name, String value) {} @Override public void setHeaders(Header[] headers) {} @Override public void removeHeader(Header header) {} @Override public void removeHeaders(String name) {} @Override public HttpResponse setStatusLine(StatusLine statusLine) { throw new UnsupportedOperationException(); } @Override public HttpResponse setStatusLine(ProtocolVersion ver, int code) { throw new UnsupportedOperationException(); } @Override public HttpResponse setStatusLine(ProtocolVersion ver, int code, String reason) { throw new UnsupportedOperationException(); } @Override public HttpResponse setStatusCode(int code) throws IllegalStateException { throw new UnsupportedOperationException(); } @Override public HttpResponse setReasonPhrase(String reason) throws IllegalStateException { throw new UnsupportedOperationException(); } @Override public HttpResponse setEntity(HttpEntity entity) { throw new UnsupportedOperationException(); } @Override public HttpResponse addHeader(HeaderIterator iterator) { throw new UnsupportedOperationException(); } @Override public HttpResponse setHeader(HeaderIterator iterator) { throw new UnsupportedOperationException(); } }
测试时直接实例化这个类:
HttpEntity testEntity = new StringEntity("test content", ContentType.TEXT_PLAIN); CloseableHttpResponse mockResponse = new MockHttpResponse(HttpStatus.SC_OK, testEntity);
这两个方案都规避了Mockito final mock的风险,且符合HttpClient的设计规范,是更稳妥的选择。
内容的提问来源于stack exchange,提问作者dinhokz
相关产品推荐
相关产品推荐

