출처: https://docs.spring.io/spring-boot/4.0-SNAPSHOT/reference/testing/test-utilities.html
Test Utilities
spring-boot의 일부로 패키징된 몇 가지 테스트 유틸리티 클래스는 애플리케이션을 테스트할 때 일반적으로 유용합니다.
ConfigDataApplicationContextInitializer
ConfigDataApplicationContextInitializer는 Spring Boot application.properties 파일을 로드하기 위해 테스트에 적용할 수 있는 ApplicationContextInitializer입니다.
다음 예제와 같이 @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파일이 Spring의Environment에 로드되도록 하는 것입니다.@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")
}
}
OutputCaptureExtension
OutputCaptureExtension은 System.out 및 System.err 출력을 캡처하는 데 사용할 수 있는 JUnit Extension입니다.
이를 사용하려면 @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은 통합 테스트에서 유용한 Spring의 RestTemplate에 대한 편리한 대안입니다.
이것은 spring-boot-restclient-test 모듈에서 제공됩니다.
vanilla 템플릿이나 Basic HTTP 인증(사용자 이름과 비밀번호 포함)을 보내는 템플릿을 얻을 수 있습니다.
어느 경우든 템플릿은 fault tolerant합니다.
이는 4xx 및 5xx 오류에 대해 예외를 발생시키지 않음으로써 테스트 친화적인 방식으로 동작한다는 것을 의미합니다.
대신 이러한 오류는 반환된 ResponseEntity와 해당 상태 코드를 통해 감지할 수 있습니다.
assertions을 위한 fluent API가 필요한 경우 mock environments와 end-to-end tests와 함께 작동하는
RestTestClient사용을 고려하세요.
Spring WebFlux를 사용하는 경우 mock environments, WebFlux integration tests, end-to-end tests와 함께 작동하는 유사한 API를 제공하는
WebTestClient사용을 고려하세요.
Apache HTTP Client(버전 5.1 이상) 사용이 권장되지만 필수는 아닙니다.
클래스패스에 있는 경우 TestRestTemplate은 클라이언트를 적절하게 구성하여 응답합니다.
Apache의 HTTP 클라이언트를 사용하는 경우 쿠키를 무시하도록 구성됩니다(따라서 템플릿은 stateless입니다).
다음 예제와 같이 통합 테스트에서 TestRestTemplate을 직접 인스턴스화할 수 있습니다:
Java
import org.junit.jupiter.api.Test;
import org.springframework.boot.restclient.test.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.restclient.test.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")
}
}
또는 WebEnvironment.RANDOM_PORT 또는 WebEnvironment.DEFINED_PORT와 함께 @SpringBootTest 어노테이션을 사용하는 경우 완전히 구성된 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.restclient.RestTemplateBuilder;
import org.springframework.boot.restclient.test.TestRestTemplate;
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.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().connectTimeout(Duration.ofSeconds(1)).readTimeout(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.restclient.RestTemplateBuilder
import org.springframework.boot.restclient.test.TestRestTemplate
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().connectTimeout(Duration.ofSeconds(1))
.readTimeout(Duration.ofSeconds(1))
}
}
}