Имитация ответа okhttp

У меня есть метод ниже, который выполняет запрос GET 3 раза, пока он не будет успешно выполнен.

Что было бы лучшим способом издеваться над этим методом? Я хочу смоделировать и протестировать код состояния 401, код состояния 500 и проверить, выполняется ли метод трижды.

В python у нас есть https://github.com/getsentry/ответы, который напрямую имитирует запросы, поэтому эти методы легко протестировать.

Есть ли что-нибудь эквивалентное в Java.

@Override
    public <T> UResponse<T> get(Request request, JSONUnmarshaler<T> unmarshaller, Gson gson) throws UException {
        int status_code = 0;
        String next = null;
        String rawJSON = null;
        JsonElement jsonelement = null;
        Boolean retry = true;
        try {
            int attempts = 3;
            while ((attempts >= 0)  && (retry) && status_code != 200){
                Response response = this.client.newCall(request).execute();

                rawJSON = response.body().string();

                jsonelement = gson.fromJson(rawJSON, JsonElement.class);

                next = gson.fromJson(jsonelement.getAsJsonObject().get("next"), String.class);

                status_code = response.code();

                if (status_code == 401) {
                    try {
                        logger.warn("token expired");
                        TimeUnit.SECONDS.sleep(5);
                        retry = true;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if ((status_code / 100 ) == 5){
                    logger.warn("gateway error");
                    retry = true;                   
                }
                attempts -= 1;
                retry = false;

            }
            if (status_code != 200){
                throw new UException();
            }
            return new UResponse<T>(status_code, next, rawJSON,
                    unmarshaller.fromJSON(gson, jsonelement.getAsJsonObject()));

        } catch (IOException e) {
            e.printStackTrace();
            throw new UException();

        }

Вы можете имитировать (с mockito, jmockit и т. д.) вызовы client.newCall(request).execute(), чтобы вернуть ожидаемый ответ и проверить количество вызовов, или, может быть, более простой способ, использовать okhttp-клиент-макет (MIT), настроить свое правило для 3 раза и проверить, что оно было потребляется

Morfic 31.01.2019 15:15

Или потенциально используйте мок-сервер

Morfic 31.01.2019 15:39

@Morfic спасибо, это было действительно полезно ..

user1050619 31.01.2019 18:47

Np, не стесняйтесь опубликовать свой ответ, как только он заработает, чтобы другие тоже могли извлечь из этого пользу. Ваше здоровье

Morfic 31.01.2019 18:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
15
4
14 414
3

Ответы 3

Это было бы трудно проверить, потому что это зацикливается. Одним из решений было бы выделить this.client.newCall(request).execute() в отдельную функцию sendRequest(Request request, int attemptsRemaining). Затем вы можете использовать программу-шпион, которая блокирует этот метод, чтобы возвращать разные ответы в зависимости от количества оставшихся попыток.
Хорошая вещь, которую я понял об okhttp, заключается в том, что вы можете просто создать поддельный ответ самостоятельно. Например,

Request mockRequest = new Request.Builder()
                .url("https://some-url.com")
                .build();
return new Response.Builder()
                .request(mockRequest)
                .protocol(Protocol.HTTP_2)
                .code(401) // status code
                .message("")
                .body(ResponseBody.create(
                        MediaType.get("application/json; charset=utf-8"),
                        "{}"
                ))
                .build();

Таким образом, вы можете создать и заглушить простой метод, который возвращает ответ, и вы в принципе готовы к тестированию.

Спасибо за это. Я не знал, что вы также можете передать запрос в Response Builder.

Kishu Agarwal 07.05.2020 10:20

Я хочу издеваться над ответом, чтобы генерировать исключение при вызове response.body().byteStream(). Как мне это сделать?

dotNETbeginner 12.01.2021 08:51

Существуют имитирующие фреймворки, которые вы можете добавить в свой список зависимостей, и это все прекрасно и модно, но я старомоден и предпочитаю просто издеваться над методами remoteCall и execute:

copy this method into your test class:

private static OkHttpClient mockHttpClient(final String serializedBody) throws IOException {
        final OkHttpClient okHttpClient = mock(OkHttpClient.class);

        final Call remoteCall = mock(Call.class);

        final Response response = new Response.Builder()
                .request(new Request.Builder().url("http://url.com").build())
                .protocol(Protocol.HTTP_1_1)
                .code(200).message("").body(
                   ResponseBody.create(
                        MediaType.parse("application/json"),
                        serializedBody
                ))
                .build();

        when(remoteCall.execute()).thenReturn(response);
        when(okHttpClient.newCall(any())).thenReturn(remoteCall);

        return okHttpClient;
    }

usage:

final OkHttpClient mockedClient = mockHttpClient("{\"key\": \"val\"}");
@Test
fun verifyFailureSingleEventListener() = runBlocking {
    val sender = createSender(webServer.url("/").toString())

    webServer.enqueue(MockResponse().setResponseCode(400))
    val testEvent1 = mutableMapOf("Click" to "Open")
    sender.sendSingleEvent(testEvent1)

    assertEquals("Failure", eventListener.getStatus())
    eventListener.resetStatus()
}

мы можем установить mockresponse, чтобы иметь код состояния 400 или другой код состояния для имитации ответа

Другие вопросы по теме