spring / / 2025. 10. 10. 06:33

[Spring Boot 번역] Test Utilities

출처: 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

OutputCaptureExtensionSystem.outSystem.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 environmentsend-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))
        }

    }

}
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유