Можно использовать тесты на стороне клиента для тестирования кода, который внутренне использует RestTemplate. Идея заключается в объявлении ожидаемых запросов и предоставлении "ответов-заглушек", чтобы можно было сосредоточиться на тестировании кода в изолированной среде (то есть без запуска сервера). В следующем примере показано, как это сделать:

Java
RestTemplate restTemplate = new RestTemplate();
MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting")).andRespond(withSuccess());
// Тестовый код, использующий вышеуказанный RestTemplate ...
mockServer.verify();
Kotlin
val restTemplate = RestTemplate()
val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(requestTo("/greeting")).andRespond(withSuccess())
// Тестовый код, использующий вышеуказанный RestTemplate ...
mockServer.verify()

В предыдущем примере MockRestServiceServer (центральный класс для тестов REST на стороне клиента) конфигурирует RestTemplate с использованием специального ClientHttpRequestFactory, который подтверждает соответствие реальных запросов ожидаемым событиям и возвращает "ответы-заглушки". В данном случае мы ожидаем запрос на /greeting и хотим вернуть ответ 200 с содержимым text/plain. При необходимости можно определить дополнительные ожидаемые запросы и ответы-заглушки. Если мы определяем ожидаемые запросы и ответы-заглушки, RestTemplate можно использовать в коде на стороне клиента обычным образом. В конце тестирования можно использовать mockServer.verify(), чтобы убедиться, что все ожидаемые события произошли.

По умолчанию запросы ожидаются в том порядке, в котором были объявлены ожидаемые события. Можно установить опцию ignoreExpectOrder при создании сервера, и в этом случае все ожидаемые события будут проверены (по порядку), чтобы найти соответствие для указанного запроса. Это означает, что запросы могут поступать в любом порядке. В следующем примере используется ignoreExpectOrder:

Java
server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
Kotlin
server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build()

Даже в случае неупорядоченных запросов по умолчанию каждый запрос разрешается выполнять лишь один раз. Метод expect предоставляет перегруженный вариант, который принимает аргумент ExpectedCount, задающий диапазон подсчета (например, once, manyTimes, max, min, between и так далее). В следующем примере используется диапазон times:

Java
RestTemplate restTemplate = new RestTemplate();
MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess());
mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess());
// ...
mockServer.verify();
Kotlin
val restTemplate = RestTemplate()
val mockServer = MockRestServiceServer.bindTo(restTemplate).build()
mockServer.expect(times(2), requestTo("/something")).andRespond(withSuccess())
mockServer.expect(times(3), requestTo("/somewhere")).andRespond(withSuccess())
// ...
mockServer.verify()

Обратите внимание, что если ignoreExpectOrder не установлен (по умолчанию), и, следовательно, запросы ожидаются в порядке объявления, то этот порядок применяется только к первому из ожидаемых запросов. Например, если "/something" ожидается два раза, а затем "/somewhere" три раза, то запрос к "/something" должен поступать перед запросом к "/somewhere", но, кроме этих последующих "/something" и "/somewhere", запросы могут поступать в любой момент.

В качестве альтернативы всему вышеперечисленному, функция поддержки тестирования на стороне клиента также предоставляет реализацию ClientHttpRequestFactory, которую можно настроить в RestTemplate для привязки к экземпляру MockMvc. Это позволяет обрабатывать запросы, используя реальную логику на стороне сервера, но без запуска сервера. В следующем примере показано, как это сделать:

Java
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
this.restTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(mockMvc));
// Тестовый код, использующий вышеуказанный RestTemplate ...
Kotlin
val mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build()
restTemplate = RestTemplate(MockMvcClientHttpRequestFactory(mockMvc))
// Тестовый код, использующий вышеуказанный RestTemplate ...

Статическое импортирование

Как и в случае с тестами на стороне сервера, текучий API-интерфейс для тестов на стороне клиента требует некоторых импортируемых статических элементов. Их легко найти с помощью поиска по MockRest*. Пользователям Eclipse нужно добавить MockRestRequestMatchers.* и MockRestResponseCreators.* в качестве "избранных статических членов" в настройках Eclipse в разделе Java → Editor → Content Assist → Favorites. Это позволит использовать автозавершение (content assist) после ввода первого символа имени статического метода. Другие IDE (например, IntelliJ) могут не требовать дополнительной настройки. Проверьте поддержку автозавершения кода для статических членов.

Другие примеры тестов REST на стороне клиента

Собственные тесты Spring MVC Test включают примеры тестов REST на стороне клиента.