Loading...
Spring Framework Reference Documentation 7.0.2의 Context Configuration with Dynamic Property Sources의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
Spring TestContext Framework는 DynamicPropertyRegistry, @DynamicPropertySource 어노테이션, 그리고 DynamicPropertyRegistrar API를 통해 dynamic 프로퍼티를 지원합니다.
dynamic property source 인프라는 원래 Testcontainers 기반 테스트로부터의 프로퍼티를 Spring 통합 테스트에 쉽게 노출할 수 있도록 설계되었습니다. 그러나, 이 기능들은 테스트의
ApplicationContext외부에서 라이프사이클이 관리되는 어떤 형태의 외부 리소스나 테스트의ApplicationContext에 의해 라이프사이클이 관리되는 빈과 함께 사용할 수 있습니다.
Dynamic 프로퍼티는 @TestPropertySource, 운영 체제의 환경, Java 시스템 프로퍼티, 또는 애플리케이션이 @PropertySource를 사용하여 선언적으로나 프로그래밍 방식으로 추가한 프로퍼티 소스로부터 로드된 것보다 더 높은 우선순위를 가집니다. 따라서, dynamic 프로퍼티는 @TestPropertySource, 시스템 프로퍼티 소스, 그리고 애플리케이션 프로퍼티 소스를 통해 로드된 프로퍼티를 선택적으로 오버라이드하는 데 사용할 수 있습니다.
DynamicPropertyRegistryDynamicPropertyRegistry는 name-value 쌍을 Environment에 추가하는 데 사용됩니다. 값은 dynamic하며 프로퍼티가 resolve될 때만 호출되는 Supplier를 통해 제공됩니다. 일반적으로 메서드 레퍼런스가 값을 제공하는 데 사용됩니다.
다음 섹션에서는 DynamicPropertyRegistry를 사용하는 방법에 대한 예제를 제공합니다.
@DynamicPropertySource클래스 레벨에 적용되는 @TestPropertySource 어노테이션과 달리, @DynamicPropertySource는 통합 테스트 클래스의 static 메서드에 적용되어 통합 테스트를 위해 로드되는 ApplicationContext의 Environment 내 PropertySources 집합에 dynamic 값들을 가진 프로퍼티를 추가할 수 있습니다.
@DynamicPropertySource로 어노테이션된 통합 테스트 클래스의 메서드는 static이어야 하며 단일 DynamicPropertyRegistry 인수를 받아야 합니다. 자세한 내용은 DynamicPropertyRegistry의 클래스 레벨 javadoc을 참고하십시오.
base 클래스에서
@DynamicPropertySource를 사용하고 subclass들 간에 dynamic 프로퍼티가 변경되기 때문에 subclass의 테스트가 실패하는 것을 발견한 경우, 각 subclass가 올바른 dynamic 프로퍼티를 가진 고유한ApplicationContext를 갖도록 base 클래스에@DirtiesContext를 어노테이션해야 할 수 있습니다.
다음 예제는 Testcontainers 프로젝트를 사용하여 Spring ApplicationContext 외부에서 Redis 컨테이너를 관리합니다. 관리되는 Redis 컨테이너의 IP 주소와 포트는 테스트의 ApplicationContext 내의 컴포넌트에 redis.host 및 redis.port 프로퍼티를 통해 제공됩니다.
이 프로퍼티는 Spring의 Environment 추상화를 통해 액세스하거나, 예를 들어 각각 @Value("${redis.host}") 및 @Value("${redis.port}")를 통해 Spring이 관리하는 컴포넌트에 직접 주입할 수 있습니다.
1@SpringJUnitConfig(/* ... */) 2@Testcontainers 3class ExampleIntegrationTests { 4 5 @Container 6 static GenericContainer redis = 7 new GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379); 8 9 @DynamicPropertySource 10 static void redisProperties(DynamicPropertyRegistry registry) { 11 registry.add("redis.host", redis::getHost); 12 registry.add("redis.port", redis::getFirstMappedPort); 13 } 14 15 // tests ... 16 17}
1@SpringJUnitConfig(/* ... */) 2@Testcontainers 3class ExampleIntegrationTests { 4 5 companion object { 6 7 @Container 8 @JvmStatic 9 val redis: GenericContainer = 10 GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379) 11 12 @DynamicPropertySource 13 @JvmStatic 14 fun redisProperties(registry: DynamicPropertyRegistry) { 15 registry.add("redis.host", redis::getHost) 16 registry.add("redis.port", redis::getFirstMappedPort) 17 } 18 } 19 20 // tests ... 21 22}
DynamicPropertyRegistrar통합 테스트 클래스에서 @DynamicPropertySource 메서드를 구현하는 대신, 테스트의 ApplicationContext 내에 DynamicPropertyRegistrar API 구현체를 빈으로 등록할 수 있습니다. 이렇게 하면 @DynamicPropertySource 메서드로는 불가능한 추가 사용 사례들을 지원할 수 있습니다.
예를 들어, DynamicPropertyRegistrar는 자체가 ApplicationContext 내의 빈이므로 컨텍스트 내의 다른 빈과 상호 작용하고, 그 빈으로부터 소스되는 dynamic 프로퍼티를 등록할 수 있습니다.
테스트의 ApplicationContext 내에서 DynamicPropertyRegistrar 인터페이스를 구현하는 어떤 빈이든 자동으로 감지되고 싱글톤 사전 인스턴스화 단계 이전에 이른 초기화되며, 그러한 빈의 accept() 메서드는 registrar를 대신하여 실제 dynamic 프로퍼티 등록을 수행하는 DynamicPropertyRegistry와 함께 호출됩니다.
다른 빈과의 어떤 상호 작용도 그 다른 빈과 그 의존성의 이른 초기화를 초래합니다.
다음 예제는 ApiServer 빈에 대한 dynamic 프로퍼티를 등록하는 람다 표현식으로 DynamicPropertyRegistrar를 구현하는 방법을 보여줍니다. api.url 프로퍼티는 Spring의 Environment 추상화를 통해 액세스하거나, 예를 들어 @Value("${api.url}")를 통해 다른 Spring이 관리하는 컴포넌트에 직접 주입할 수 있으며, api.url 프로퍼티의 값은 ApiServer 빈으로부터 동적으로 조회됩니다.
1@Configuration 2class TestConfig { 3 4 @Bean 5 ApiServer apiServer() { 6 return new ApiServer(); 7 } 8 9 @Bean 10 DynamicPropertyRegistrar apiPropertiesRegistrar(ApiServer apiServer) { 11 return registry -> registry.add("api.url", apiServer::getUrl); 12 } 13}
1@Configuration 2class TestConfig { 3 4 @Bean 5 fun apiServer(): ApiServer { 6 return ApiServer() 7 } 8 9 @Bean 10 fun apiPropertiesRegistrar(apiServer: ApiServer): DynamicPropertyRegistrar { 11 return registry -> registry.add("api.url", apiServer::getUrl) 12 } 13}
Context Configuration with Test Property Sources
Loading a WebApplicationContext