web-dev-qa-db-ja.com

テストに役立つCloseableHttpResponseオブジェクトを作成するにはどうすればよいですか?

私は、ユニットテストの1つで返される CloseableHttpResponse モックオブジェクトを作成しようとしていますが、そのコンストラクタがありません。私はこれを見つけました DefaultHttpResponseFactory ですが、それはHttpResponseを作成するだけです。 CloseableHttpResponseを作成する簡単な方法は何ですか?テストで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*/)
18
Popcorn

次の手順に従ってください。

1. mock it(例: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);
26
nnguyen07

この質問が出されて久しぶりですが、使用したソリューションを提供したいと思います。

BasicHttpResponseクラスを拡張し、CloseableHttpResponseインターフェイスを実装する小さなクラスを作成しました(これには、応答を閉じるメソッドしかありません)。 BasicHttpResponseクラスにはほとんどすべての設定メソッドが含まれているため、次のコードで必要なフィールドをすべて設定できます。

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

基本的に、実際のコードで使用されるすべてのフィールドを設定します。これには、ファイルからストリームへの模擬応答コンテンツの読み取りも含まれます。

1
superM

私もモックではなく具体的​​なCloseableHttpResponseを作成したかったので、Apache HTTPクライアントのソースコードで追跡しました。

MainClientExec では、executeからのすべての戻り値は次のようになります。

return new HttpResponseProxy(response, connHolder);

connHolderはnullにすることができます。

HttpResponseProxy は、connHolderをクローズする薄いラッパーです。残念ながら、これはパッケージで保護されているため、(必ずしも)表示されません。

私がしたことは「PublicHttpResponseProxy」を作成することでした

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にバンプし、null接続ハンドラーを持つコンストラクターを提供します。

これで具体的なCloseableHttpResponseをインスタンス化できます

CloseableHttpResponse response = new PublicHttpResponseProxy(basicResponse);

通常の警告が適用されます。プロキシはパッケージで保護されているため、公式APIの一部ではないため、後で使用できないようにサイコロを振っている可能性があります。一方、それほど多くはないので、独自のバージョンを簡単に作成できます。カットアンドペーストがあるかもしれませんが、それほど悪くはありません。

1
Rob

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;
}
0
Popcorn

既存の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 { }

}
0
LoganL