Java 如何创建 CloseableHttpResponse 对象来帮助测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19846526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I create a CloseableHttpResponse object to help testing?
提问by Popcorn
I'm trying to construct a CloseableHttpResponsemock object to be returned in one of my unit tests, but there's no constructor for it. I found this DefaultHttpResponseFactory, but it only makes a HttpResponse. What's a simple way to construct a CloseableHttpResponse? Do I need to call execute()
in my test and then set the statusLine
and entity
? That seems like a weird approach.
我正在尝试构造一个CloseableHttpResponse模拟对象以在我的单元测试之一中返回,但没有构造函数。我找到了这个DefaultHttpResponseFactory,但它只生成了一个 HttpResponse。构建 CloseableHttpResponse 的简单方法是什么?我是否需要调用execute()
我的测试然后设置statusLine
和entity
?这似乎是一种奇怪的方法。
Here's the method I'm trying to mock:
这是我试图模拟的方法:
public static CloseableHttpResponse getViaProxy(String url, String ip, int port, String username,
String password) {
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(ip, port),
new UsernamePasswordCredentials(username, password));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider).build();
try {
RequestConfig config = RequestConfig.custom()
.setProxy(new HttpHost(ip, port))
.build();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(config);
LOGGER.info("executing request: " + httpGet.getRequestLine() + " via proxy ip: " + ip + " port: " + port +
" username: " + username + " password: " + password);
CloseableHttpResponse response = null;
try {
return httpclient.execute(httpGet);
} catch (Exception e) {
throw new RuntimeException("Could not GET with " + url + " via proxy ip: " + ip + " port: " + port +
" username: " + username + " password: " + password, e);
} finally {
try {
response.close();
} catch (Exception e) {
throw new RuntimeException("Could not close response", e);
}
}
} finally {
try {
httpclient.close();
} catch (Exception e) {
throw new RuntimeException("Could not close httpclient", e);
}
}
}
Here's the mock code using PowerMockito:
这是使用 PowerMockito 的模拟代码:
mockStatic(HttpUtils.class);
when(HttpUtils.getViaProxy("http://www.google.com", anyString(), anyInt(), anyString(), anyString()).thenReturn(/*mockedCloseableHttpResponseObject goes here*/)
回答by Popcorn
nvm, I ended up just hacking it by using execute()
:
nvm,我最终只是通过使用来破解它execute()
:
private CloseableHttpResponse getMockClosesableHttpResponse(HttpResponse response) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse closeableHttpResponse = httpClient.execute(new HttpGet("http://www.test.com"));
closeableHttpResponse.setEntity(response.getEntity());
closeableHttpResponse.setStatusLine(response.getStatusLine());
return closeableHttpResponse;
}
回答by nnguyen07
Follow these steps may help:
遵循以下步骤可能会有所帮助:
1.mock it (ex. mockito)
1.mock it(例如mockito)
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
HttpEntity entity = mock(HttpEntity.class);
2.apply some rules
2.应用一些规则
when(response.getStatusLine()).thenReturn(new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "FINE!"));
when(entity.getContent()).thenReturn(getClass().getClassLoader().getResourceAsStream("result.txt"));
when(response.getEntity()).thenReturn(entity);
3.use it
3.使用它
when(httpClient.execute((HttpGet) any())).thenReturn(response);
回答by Rob
I wanted to create a concrete CloseableHttpResponse rather than a mock, too, so I tracked it down in the Apache HTTP client source code.
我也想创建一个具体的 CloseableHttpResponse 而不是模拟,所以我在 Apache HTTP 客户端源代码中找到了它。
In MainClientExec, all the return values from execute look like:
在MainClientExec 中,execute 的所有返回值如下所示:
return new HttpResponseProxy(response, connHolder);
where connHolder can be null.
其中 connHolder 可以为 null。
HttpResponseProxyis just a thin wrapper that does a close on the connHolder. Unfortunately, it is package protected, so it's not (necessarily) visible.
HttpResponseProxy只是一个对 connHolder 进行关闭的薄包装器。不幸的是,它是包保护的,所以它(必然)不可见。
What I did was create a "PublicHttpResponseProxy"
我所做的是创建一个“PublicHttpResponseProxy”
package org.apache.http.impl.execchain;
import org.apache.http.HttpResponse;
public class PublicHttpResponseProxy extends HttpResponseProxy {
public PublicHttpResponseProxy(HttpResponse original) {
super(original, null);
}
}
Must be in package "org.apache.http.impl.execchain" (!) Basically bumps the visiblity to public and provide a constructor with null connection handler.
必须在包“org.apache.http.impl.execchain”(!)中,基本上将可见性提高到公共,并提供一个带有空连接处理程序的构造函数。
Now I can instantiate a concrete CloseableHttpResponse with
现在我可以实例化一个具体的 CloseableHttpResponse
CloseableHttpResponse response = new PublicHttpResponseProxy(basicResponse);
The usual caveats apply. Since the proxy is package protected, it's not a part of the official API, so you might be rolling the dice that it will be unavailable later. On the other hand, there's not much to it, so you could easily just write your own version of it. There would be some cut-and-pasting, but it wouldn't be so bad.
通常的警告适用。由于代理是包保护的,它不是官方 API 的一部分,因此您可能会赌它以后将不可用。另一方面,它没有太多内容,因此您可以轻松地编写自己的版本。会有一些剪切和粘贴,但不会那么糟糕。
回答by superM
It's been a while since this question has been asked, but I want to provide a solution I used.
自从提出这个问题已经有一段时间了,但我想提供一个我使用过的解决方案。
I've created a small class which extends the BasicHttpResponse
class and implements the CloseableHttpResponse
interface (which has nothing but a method to close the response). Since the BasicHttpResponse
class contains setter methods for pretty much everything, I can set all the fields I need with the following piece of code:
我创建了一个小类,它扩展了BasicHttpResponse
类并实现了CloseableHttpResponse
接口(它只有一个关闭响应的方法)。由于BasicHttpResponse
该类包含几乎所有内容的 setter 方法,我可以使用以下代码设置我需要的所有字段:
public static CloseableHttpResponse buildMockResponse() throws FileNotFoundException {
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
String reasonPhrase = "OK";
StatusLine statusline = new BasicStatusLine(protocolVersion, HttpStatus.SC_OK, reasonPhrase);
MockCloseableHttpResponse mockResponse = new MockCloseableHttpResponse(statusline);
BasicHttpEntity entity = new BasicHttpEntity();
URL url = Thread.currentThread().getContextClassLoader().getResource("response.txt");
InputStream instream = new FileInputStream(new File(url.getPath()));
entity.setContent(instream);
mockResponse.setEntity(entity);
return mockResponse;
}
I basically set all the fields, which are used by the actual code. This also includes reading a mock response content from a file into a stream.
我基本上设置了实际代码使用的所有字段。这还包括将模拟响应内容从文件读取到流中。
回答by LoganL
Its easy enough to just create a test implementation piggybacking off the existing BasicHttpResponse type:
它很容易创建一个搭载现有 BasicHttpResponse 类型的测试实现:
public class TestCloseableHttpResponse extends BasicHttpResponse implements CloseableHttpResponse {
public TestCloseableHttpResponse(StatusLine statusline, ReasonPhraseCatalog catalog, Locale locale) {
super(statusline, catalog, locale);
}
public TestCloseableHttpResponse(StatusLine statusline) {
super(statusline);
}
public TestCloseableHttpResponse(ProtocolVersion ver, int code, String reason) {
super(ver, code, reason);
}
@Override
public void close() throws IOException { }
}