Подтвердить что ты не робот

Как создать объект CloseableHttpResponse для тестирования?

Я пытаюсь построить объект CloseableHttpResponse, который будет возвращен в одном из моих модульных тестов, но нет конструктора для него, Я нашел этот DefaultHttpResponseFactory, но он только делает HttpResponse. Какой простой способ построить CloseableHttpResponse? Мне нужно вызвать execute() в моем тесте, а затем установить statusLine и entity? Это похоже на странный подход.

Здесь метод, который я пытаюсь высмеять:

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*/)
4b9b3361

Ответ 1

Выполните следующие действия:

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

Ответ 2

Я хотел создать конкретный CloseableHttpResponse, а не макет, поэтому я отследил его в исходном коде клиента Apache HTTP.

В MainClientExec все возвращаемые значения из выполнения выглядят следующим образом:

return new HttpResponseProxy(response, connHolder);

где connHolder может быть нулевым.

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" (!) В основном ударяет видимость для публики и предоставляет конструктору нулевой обработчик подключений.

Теперь я могу создать конкретный CloseableHttpResponse с помощью

CloseableHttpResponse response = new PublicHttpResponseProxy(basicResponse);

Применяются обычные оговорки. Поскольку прокси-сервер защищен пакетом, он не является частью официального API, поэтому вы можете перевернуть кости, которые позже будут недоступны. С другой стороны, там не так много, поэтому вы можете просто написать свою собственную версию. Было бы немного вырезания и вставки, но это было бы не так уж плохо.

Ответ 3

Прошло некоторое время с тех пор, как был задан этот вопрос, но я хочу предоставить решение, которое я использовал.

Я создал небольшой класс, который расширяет класс 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;
}

Я в основном устанавливаю все поля, которые используются фактическим кодом. Это также включает чтение фиктивного содержимого ответа из файла в поток.

Ответ 4

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