JavaRush /Курси /Модуль 5. Spring /Тестування програми на Spring Boot, частина 3

Тестування програми на Spring Boot, частина 3

Модуль 5. Spring
Рівень 15 , Лекція 12
Відкрита

ConfigDataApplicationContextInitializer

ConfigDataApplicationContextInitializer — це ApplicationContextInitializer, який можна застосовувати до тестів для завантаження файлів application.properties для Spring Boot. Можна використовувати його, якщо немає потреби в повному наборі функцій, передбачених анотацією @SpringBootTest, як це показано в наступному прикладі:

Java
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class) class MyConfigFileTests { // ... } 
Kotlin
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer import org.springframework.test.context.ContextConfiguration @ContextConfiguration(classes = [Config::class], initializers = [ConfigDataApplicationContextInitializer::class]) class MyConfigFileTests { // ... } 
Використання виключно класу ConfigDataApplicationContextInitializer не забезпечить підтримку впровадження анотації @Value("${…}"). Його єдине завдання — забезпечити завантаження файлів application.properties до Environment для Spring. Для забезпечення підтримки анотації @Value необхідно або додатково налаштувати PropertySourcesPlaceholderConfigurer, або використовувати анотацію @SpringBootTest, яка автоматично його налаштує за тебе.

TestPropertyValues

Клас TestPropertyValues дозволяє швидко додати властивості до ConfigurableEnvironment або ConfigurableApplicationContext. Можна викликати його за допомогою рядків key=value, як показано нижче:

Java
import org.junit.jupiter.api.Test; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; class MyEnvironmentTests { @Test void testPropertySources() { MockEnvironment environment = New MockEnvironment(); TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment); assertThat(environment.getProperty("name")).isEqualTo("Boot"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.boot.test.util.TestPropertyValues import org.springframework.mock.env.MockEnvironment class MyEnvironmentTests { @Test fun testPropertySources() { val environment = MockEnvironment() TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment) assertThat(environment.getProperty("name")).isEqualTo("Boot") } } 

OutputCapture

OutputCapture — це Extension для JUnit, яке можна використовувати для захоплення виведення System.out та System.err. Для використання додай анотацію @ExtendWith(OutputCaptureExtension.class) і впровадь CapturedOutput як аргумент до конструктора твого тестового класу або тестового методу наступним чином:

Java
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(OutputCaptureExtension.class) class MyOutputCaptureTests { @Test void testName(CapturedOutput output) { System.out.println("Hello World!"); assertThat(output).contains("World"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.boot.test.system.CapturedOutput import org.springframework.boot.test.system.OutputCaptureExtension @ExtendWith(OutputCaptureExtension::class) class MyOutputCaptureTests { @Test fun testName(output: CapturedOutput?) { println("Hello World!") assertThat(output).contains("World") } } 

TestRestTemplate

TestRestTemplate — це зручна альтернатива RestTemplate зі Spring, яка корисна в межах інтеграційних тестів. Можна отримати ванільний шаблон або той, який надсилає базову HTTP-автентифікацію (з ім'ям користувача та паролем). У будь-якому випадку шаблон є стійким до збоїв. Це означає, що його логіка роботи зручна для тестування і не генерує виняток при помилках 4xx та 5xx. Натомість такі помилки можна виявити через повертаний ResponseEntity та його код стану.

Spring Framework 5.0 передбачає новий WebTestClient, який добре підходить і для інтеграційних тестів у WebFlux, і для наскрізного тестування у WebFlux та MVC. На відміну від TestRestTemplate, він передбачає текучий API для додавання тверджень.

Рекомендується — хоч і не обов'язково — використовувати Apache HTTP Client (версії 4.3.2 або вище). Якщо він знаходиться у твоєму classpath, шаблон TestRestTemplate зреагує на це та налаштує клієнт відповідним чином. Якщо ти використовуєш HTTP-клієнт від Apache, додаються деякі додаткові функції для тестування:

  • Переправлення не відстежуються (тому можна додавати твердження для розташування відповіді).

  • Файли cookie ігноруються (тому шаблон не зберігає стан).

Екземпляр TestRestTemplate можна створити безпосередньо в інтеграційних тестах, як показано в наступному прикладі:

Java
import org.junit.jupiter.api.Test; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; class MyTests { private final TestRestTemplate template = новий TestRestTemplate(); @Test void testRequest() { ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class); assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.boot.test.web.client.TestRestTemplate class MyTests { private val template = TestRestTemplate() @Test fun testRequest() { val headers = template.getForEntity("https://myhost.example.com/example", String::class.java) assertThat(headers.headers.location).hasHost("other.example.com") } } 

До того ж, якщо ти використовуєш анотацію @SpringBootTest з WebEnvironment.RANDOM_PORT або WebEnvironment.DEFINED_PORT, можна впровадити повністю конфігурований TestRestTem та почати його використовувати. За потреби додаткові налаштування можна застосувати через бін RestTemplateBuilder. Будь-які URL-адреси, в яких не вказано хост і порт, автоматично підключаються до вбудованого сервера, як показано в наступному прикладі:

Java
import java.time.Duration; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MySpringBootTests { @Autowired private TestRestTemplate template; @Test void testRequest() { HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders(); assertThat(headers.getLocation()).hasHost("other.example.com"); } @TestConfiguration(proxyBeanMethods = false) static class RestTemplateBuilderConfiguration { @Bean RestTemplateBuilder restTemplateBuilder() { return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1)) .setReadTimeout(Duration.ofSeconds(1)); } } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest.WebEnvironment import org.springframework.boot.test.context.TestConfiguration import org.springframework.boot.test.web.client.TestRestTemplate import org.springframework.boot.web.client.RestTemplateBuilder import org.springframework.context.annotation.Bean import java.time.Duration @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MySpringBootTests(@Autowired val template: TestRestTemplate) { @Test fun testRequest() { val headers = template.getForEntity("/example", String::class.java).headers assertThat(headers.location).hasHost("other.example.com") } @TestConfiguration(proxyBeanMethods = false) internal class RestTemplateBuilderConfiguration { @Bean fun restTemplateBuilder(): RestTemplateBuilder { return RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1)) .setReadTimeout(Duration.ofSeconds(1)) } } } 
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ