«1. Введение

Эта статья представляет собой краткое введение в аннотацию @RestClientTest.

Новая аннотация помогает упростить и ускорить тестирование клиентов REST в ваших приложениях Spring.

2. Поддержка клиента REST в Spring Boot до версии 1.4

Spring Boot — это удобный фреймворк, который предоставляет множество автоматически настраиваемых компонентов Spring с типичными настройками, которые позволяют вам меньше концентрироваться на настройке приложения Spring и больше на своем код и бизнес-логика.

Но в версии 1.3 мы не получаем много помощи, когда хотим создать или протестировать клиентов служб REST. Его поддержка клиентов REST не очень глубока.

Для создания клиента для REST API обычно используется экземпляр RestTemplate. Обычно его необходимо настроить перед использованием, и его конфигурация может различаться, поэтому Spring Boot не предоставляет универсально настроенного bean-компонента RestTemplate.

То же самое касается тестирования клиентов REST. До Spring Boot 1.4.0 процедура тестирования клиента Spring REST не сильно отличалась от процедуры тестирования любого другого приложения на базе Spring. Вы должны создать экземпляр MockRestServiceServer, привязать его к тестируемому экземпляру RestTemplate и предоставить ему фиктивные ответы на запросы, например: загружаются в контекст, чтобы ускорить время загрузки контекста (и, следовательно, время выполнения теста).

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer =
  MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting"))
  .andRespond(withSuccess());

// Test code that uses the above RestTemplate ...

mockServer.verify();

3. Новые функции клиента REST в Spring Boot 1.4+

В Spring Boot 1.4 команда приложила все усилия, чтобы упростить и ускорить создание и тестирование клиентов REST.

Итак, давайте проверим новые возможности.

3.1. Добавление Spring Boot в ваш проект

Во-первых, вам нужно убедиться, что ваш проект использует Spring Boot 1.4.x или выше:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Новейшие версии релизов можно найти здесь.

3.2. RestTemplateBuilder

Spring Boot предоставляет как автоматически настроенный RestTemplateBuilder для упрощения создания RestTemplates, так и соответствующую аннотацию @RestClientTest для тестирования клиентов, созданных с помощью RestTemplateBuilder. Вот как можно создать простой REST-клиент с автоматически внедряемым RestTemplateBuilder:

@Service
public class DetailsServiceClient {

    private final RestTemplate restTemplate;

    public DetailsServiceClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }

    public Details getUserDetails(String name) {
        return restTemplate.getForObject("/{name}/details",
          Details.class, name);
    }
}

Обратите внимание, что мы не связывали явно экземпляр RestTemplateBuilder с конструктором. Это возможно благодаря новой функции Spring, называемой внедрением неявного конструктора, которая обсуждается в этой статье.

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

3.3. @RestClientTest

Для тестирования такого клиента REST, созданного с помощью RestTemplateBuilder, вы можете использовать исполняемый SpringRunner тестовый класс, аннотированный @RestClientTest. Эта аннотация отключает полную автоматическую настройку и применяет только конфигурацию, относящуюся к клиентским тестам REST, т. е. автоматическую настройку Jackson или GSON и компоненты @JsonComponent, но не обычные компоненты @Component.

@RestClientTest обеспечивает автоматическую настройку поддержки Jackson и GSON, а также добавляет в контекст предварительно настроенные экземпляры RestTemplateBuilder и MockRestServiceServer. Тестируемый компонент указывается с помощью атрибута value или component аннотации @RestClientTest:

@RunWith(SpringRunner.class)
@RestClientTest(DetailsServiceClient.class)
public class DetailsServiceClientTest {

    @Autowired
    private DetailsServiceClient client;

    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void setUp() throws Exception {
        String detailsString = 
          objectMapper.writeValueAsString(new Details("John Smith", "john"));
        
        this.server.expect(requestTo("/john/details"))
          .andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON));
    }

    @Test
    public void whenCallingGetUserDetails_thenClientMakesCorrectCall() 
      throws Exception {

        Details details = this.client.getUserDetails("john");

        assertThat(details.getLogin()).isEqualTo("john");
        assertThat(details.getName()).isEqualTo("John Smith");
    }
}

Во-первых, нам нужно убедиться, что этот тест выполняется с помощью SpringRunner, добавив аннотацию @RunWith(SpringRunner.class).

Итак, что нового?

Во-первых, аннотация @RestClientTest позволяет нам точно указать тестируемый сервис — в нашем случае это класс DetailsServiceClient. Этот сервис будет загружен в тестовый контекст, а все остальное будет отфильтровано.

Это позволяет нам автоматически подключать экземпляр DetailsServiceClient внутри нашего теста и оставлять все остальное снаружи, что ускоряет загрузку контекста.

Во-вторых, поскольку экземпляр MockRestServiceServer также настроен для теста с аннотацией @RestClientTest (и привязан к экземпляру DetailsServiceClient для нас), мы можем просто внедрить его и использовать.

«Наконец, поддержка JSON для @RestClientTest позволяет нам внедрить экземпляр ObjectMapper Джексона, чтобы подготовить значение фиктивного ответа MockRestServiceServer.

Осталось только выполнить вызов нашего сервиса и проверить результаты.

4. Заключение

В этой статье мы обсудили новую аннотацию @RestClientTest, которая позволяет легко и быстро тестировать клиенты REST, созданные с помощью Spring.

Исходный код статьи доступен на GitHub.