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 = new 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, можно внедрить полностью сконфигурированный TestRestTemplate и начать его использовать. При необходимости дополнительные настройки можно применить через бин 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))
        }
    }
}