MockRestServiceServer имитирует время ожидания интеграции в тесте интеграции

Я пишу какой-то интеграционный тест на моем контроллере REST, используя MockRestServiceServer, чтобы издеваться над бэкэнд-поведением. То, что я пытаюсь достичь сейчас, - это симулировать очень медленный ответ от бэкэнд, который в конечном итоге приведет к таймауту в моем приложении. Похоже, что он может быть реализован с помощью WireMock, но в данный момент я хотел бы придерживаться MockRestServiceServer.

Я создаю сервер следующим образом:

myMock = MockRestServiceServer.createServer(asyncRestTemplate);

А потом я издеваюсь над моим бэкэнд-поведением, например:

myMock.expect(requestTo("http://myfakeurl.blabla"))
            .andExpect(method(HttpMethod.GET))
            .andRespond(withSuccess(myJsonResponse, MediaType.APPLICATION_JSON));

Можно ли добавить какой-либо задержкой или тайм-аутом или другим типом задержки для ответа (или, может быть, всего издевавшегося сервера или даже моего asyncRestTemplate)? Или мне нужно просто переключиться на WireMock или Restito?

Ответ 1

Вы можете реализовать эту функциональность теста следующим образом (Java 8):

myMock
    .expect(requestTo("http://myfakeurl.blabla"))
    .andExpect(method(HttpMethod.GET))
    .andRespond(request -> {
        try {
            Thread.sleep(TimeUnit.SECONDS.toMillis(1));
        } catch (InterruptedException ignored) {}
        return new MockClientHttpResponse(myJsonResponse, HttpStatus.OK);
    });

Но я должен предупредить вас, что, поскольку MockRestServiceServer просто заменяет RestTemplate requestFactory, любые ваши настройки requestFactory будут потеряны в тестовой среде.

Ответ 2

Подход, на который вы можете пойти: Указание тела ответа либо ресурсом класса Path, либо нормальным содержимым строки. Более подробная версия того, что предложил Скиев выше

.andRespond(request -> {
            try {
                Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // Delay
            } catch (InterruptedException ignored) {}
            return withStatus(OK).body(responseBody).contentType(MediaType.APPLICATION_JSON).createResponse(request);
        });

Ответ 3

В Restito существует функция buil-in для моделирования таймаута:

import static com.xebialabs.restito.semantics.Action.delay

whenHttp(server).
   match(get("/something")).
   then(delay(201), stringContent("{}"))

Ответ 4

В общем, вы можете определить свой пользовательский обработчик запросов и сделать противный Thread.sleep() там.

Это возможно в Restito с чем-то вроде этого.

Action waitSomeTime = Action.custom(input -> {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return input;
});

whenHttp(server).match(get("/asd"))
        .then(waitSomeTime, ok(), stringContent("Hello World"))

Не уверен насчет Spring. Вы можете легко попробовать. Проверьте DefaultResponseCreator для вдохновения.

Ответ 5

Если вы контролируете тайм-аут в своем http-клиенте и используете, например, 1 секунду, вы можете использовать фиктивную задержку сервера

new MockServerClient("localhost", 1080)
.when(
    request()
        .withPath("/some/path")
)
.respond(
    response()
        .withBody("some_response_body")
        .withDelay(TimeUnit.SECONDS, 10)
);

Если вы хотите сбросить соединение в Mock Server, используйте действие mock server error

new MockServerClient("localhost", 1080)
.when(
    request()
        .withPath("/some/path")
)
.error(
    error()
        .withDropConnection(true)
);