mockito 如何创建ClosebleHttpResponse对象来帮助测试?

pbgvytdp  于 2022-11-08  发布在  其他
关注(0)|答案(9)|浏览(408)

我试图构造一个CloseableHttpResponse模拟对象,在我的一个单元测试中返回,但是没有它的构造函数。我找到了这个DefaultHttpResponseFactory,但是它只生成了一个HttpResponse。构造ClosebleHttpResponse的简单方法是什么?我需要在我的测试中调用execute(),然后设置statusLineentity吗?这似乎是一个奇怪的方法。
下面是我想嘲笑的方法:

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);
        }
    }
}

下面是使用PowerMockito的模拟代码:

mockStatic(HttpUtils.class);
    when(HttpUtils.getViaProxy("http://www.google.com", anyString(), anyInt(), anyString(), anyString()).thenReturn(/*mockedCloseableHttpResponseObject goes here*/)
s2j5cfk0

s2j5cfk01#

遵循以下步骤可能会有所帮助:
1.嘲笑它(例如mockito)

CloseableHttpResponse response = mock(CloseableHttpResponse.class);
HttpEntity entity = mock(HttpEntity.class);

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.使用它

when(httpClient.execute((HttpGet) any())).thenReturn(response);
cczfrluj

cczfrluj2#

这个问题已经有一段时间没有被问到了,但我想提供一个我使用过的解决方案。
我创建了一个扩展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;
}

我基本上设置了所有字段,这些字段由实际代码使用。这还包括将模拟响应内容从文件读取到流中。

atmip9wb

atmip9wb3#

我也想创建一个具体的ClosebleHttpResponse,而不是一个模拟,所以我在Apache HTTP客户端源代码中找到了它。
MainClientExec中,execute的所有返回值如下所示:

return new HttpResponseProxy(response, connHolder);

其中connHolder可以为空。
HttpResponseProxy只是一个很薄的 Package 器,用于关闭connHolder。不幸的是,它是受包保护的,因此(不一定)可见。
我所做的是创建一个“公共HttpResponseProxy”

package org.apache.http.impl.execchain;

import org.apache.http.HttpResponse;

public class PublicHttpResponseProxy extends HttpResponseProxy {

    public PublicHttpResponseProxy(HttpResponse original) {
        super(original, null);
    }
}

必须在包“org.apache.http.impl.execchain”(!)中,基本上将可见性转换为public,并提供一个带有空连接处理程序的构造函数。
现在,我可以使用以下命令示例化一个具体的ClosebleHttpResponse

CloseableHttpResponse response = new PublicHttpResponseProxy(basicResponse);

通常的警告也适用。由于代理是包保护的,它不是官方API的一部分,所以你可能会赌它以后会不可用。另一方面,它没有太多内容,所以你可以很容易地编写自己的版本。会有一些剪切和粘贴,但不会太糟糕。

ddhy6vgd

ddhy6vgd4#

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;
}
t2a7ltrp

t2a7ltrp5#

只需创建一个测试实现,并附带现有的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 { }

}
t40tm48m

t40tm48m6#

这对我很有效:

HttpEntity httpEntity = mock(HttpEntity.class); // mocked

CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class) // mocked

CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient .class) // mocked

String resultJson =
    "{\"key\": \"value\"}";

InputStream is = new ByteArrayInputStream( resultJson.getBytes() );

Mockito.when(httpEntity.getContent()).thenReturn(is);
Mockito.when( httpEntity.getContentLength() ).thenReturn(Long.valueOf(.length()));
StatusLine statusLine = new BasicStatusLine(new ProtocolVersion("http", 1, 1), 200, "success");
Mockito.when(httpEntity.toString()).thenReturn(resultJson);
Mockito.when(closeableHttpResponse.getEntity()).thenReturn(httpEntity);
Mockito.when(closeableHttpResponse.getStatusLine()).thenReturn(statusLine);

Mockito.when(closeableHttpClient.execute((HttpPost) 
Mockito.any())).thenReturn(closeableHttpResponse);
sc4hvdpw

sc4hvdpw7#

我的方法是创建一个简单的CloseableHttpResponse,然后在模拟CloseableHttpClient时使用它作为响应。

public class TestCloseableHttpResponse extends BasicHttpResponse implements CloseableHttpResponse {

    public TestCloseableHttpResponse(ProtocolVersion ver, int code, String reason) {
        super(ver, code, reason);
    }

        public TestCloseableHttpResponse(ProtocolVersion ver, int code, String reason, String entityString) {
            this(ver, code, reason);
            setEntity(new StringEntity(entityString, Charset.defaultCharset()));
        }

    @Override
    public void close() throws IOException {
        // we don't care about closing any connections in mocking tests
    }
}

然后在测试中,您可以简单地编写:

CloseableHttpResponse okResponse = new TestCloseableHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");

如果你想得到一些Entity

CloseableHttpResponse okResponse = new TestCloseableHttpResponse(HttpVersion.HTTP_1_1, 200, "OK", "some text");

在你的情况下,你可能想这样使用mock it:

when(httpClient.execute(any())).thenReturn(okResponse);
vshtjzan

vshtjzan8#

在我的用例中,我在RestTemplate中使用httpClient。所以我还需要模拟一些额外的方法,如下所示:

CloseableHttpResponse response = mock(CloseableHttpResponse.class);
HttpEntity entity = mock(HttpEntity.class);
when(response.getStatusLine()).thenReturn(new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"));
when(entity.getContent()).thenReturn(new ByteArrayInputStream("{\"response\": \"test\"}".getBytes()));
when(response.getAllHeaders()).thenReturn(new BasicHeader[]{new BasicHeader("test", "test")});
when(response.getEntity()).thenReturn(entity);
doNothing().when(response).close();

when(httpClient.execute(any(), (HttpRequest) any(), (HttpContext) any())).thenReturn(response);
lh80um4z

lh80um4z9#

使用mockito inline,即here中提到的,它允许您模拟final类

相关问题