Context Configuration with Dynamic Property Sources
Spring TestContext 框架通过 @DynamicPropertySource
注释和 DynamicPropertyRegistry
提供对动态特性的支持。
The Spring TestContext Framework provides support for dynamic properties via the
@DynamicPropertySource
annotation and the DynamicPropertyRegistry
.
The |
与应用于类级别的 @TestPropertySource
注释相反,可以将 @DynamicPropertySource
应用于集成测试类中的 static
方法或测试 @Configuration
类中的 @Bean
方法,以便将具有动态值的属性添加到 Environment
中 PropertySources
的集合,以供集成测试加载的 ApplicationContext
。
In contrast to the
@TestPropertySource
annotation that is applied at the class level, @DynamicPropertySource
can be applied to
static
methods in integration test classes or to @Bean
methods in test
@Configuration
classes in order to add properties with dynamic values to the set of
PropertySources
in the Environment
for the ApplicationContext
loaded for the
integration test.
DynamicPropertyRegistry
用于向 Environment
添加名称-值对。通过仅在解析属性时调用的 Supplier
提供和动态提供值。典型情况下,方法引用用于提供值。
A DynamicPropertyRegistry
is used to add name-value pairs to the Environment
.
Values are dynamic and provided via a Supplier
which is only invoked when the property
is resolved. Typically, method references are used to supply values.
注释了 @DynamicPropertySource
的集成测试类中的方法必须是 static
的,并且必须接受单个 DynamicPropertyRegistry
参数。
Methods in integration test classes that are annotated with @DynamicPropertySource
must
be static
and must accept a single DynamicPropertyRegistry
argument.
带 @DynamicPropertySource
注释的 @Bean
方法要么接受 type
DynamicPropertyRegistry
的参数,要么访问其包含 @Configuration
类中自动注入的 DynamicPropertyRegistry
实例。但请注意,与 DynamicPropertyRegistry
交互的 @Bean
方法不需要用 @DynamicPropertySource
注释,除非它们需要强制上下文中 bean 的热加载。有关详细信息,请参见 DynamicPropertyRegistry
的类级别 javadoc。
@Bean
methods annotated with @DynamicPropertySource
may either accept an argument of
type DynamicPropertyRegistry
or access a DynamicPropertyRegistry
instance autowired
into their enclosing @Configuration
class. Note, however, that @Bean
methods which
interact with a DynamicPropertyRegistry
are not required to be annotated with
@DynamicPropertySource
unless they need to enforce eager initialization of the bean
within the context. See the class-level javadoc for DynamicPropertyRegistry
for details.
如果你在基类中使用 If you use |
以下示例使用 Testcontainers 项目来管理 Spring ApplicationContext
外部的 Redis 容器。受管理的 Redis 容器的 IP 地址和端口通过 redis.host
和 redis.port
特性向测试的 ApplicationContext
中的组件提供。这些特性可通过 Spring 的 Environment
抽象进行访问,或直接注入 Spring 管理的组件 – 例如,分别通过 @Value("${redis.host}")
和 @Value("${redis.port}")
。
The following example uses the Testcontainers project to manage a Redis container outside
of the Spring ApplicationContext
. The IP address and port of the managed Redis
container are made available to components within the test’s ApplicationContext
via the
redis.host
and redis.port
properties. These properties can be accessed via Spring’s
Environment
abstraction or injected directly into Spring-managed components – for
example, via @Value("${redis.host}")
and @Value("${redis.port}")
, respectively.
-
Java
-
Kotlin
@SpringJUnitConfig(/* ... */)
@Testcontainers
class ExampleIntegrationTests {
@Container
static GenericContainer redis =
new GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379);
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("redis.host", redis::getHost);
registry.add("redis.port", redis::getFirstMappedPort);
}
// tests ...
}
@SpringJUnitConfig(/* ... */)
@Testcontainers
class ExampleIntegrationTests {
companion object {
@Container
@JvmStatic
val redis: GenericContainer =
GenericContainer("redis:5.0.3-alpine").withExposedPorts(6379)
@DynamicPropertySource
@JvmStatic
fun redisProperties(registry: DynamicPropertyRegistry) {
registry.add("redis.host", redis::getHost)
registry.add("redis.port", redis::getFirstMappedPort)
}
}
// tests ...
}
以下示例演示如何将 DynamicPropertyRegistry
和 @DynamicPropertySource
与 @Bean
方法结合使用。可以通过 Spring 的 Environment
抽象访问 api.url
特性,或直接注入其他 Spring 管理的组件 – 例如,通过 @Value("${api.url}")
。api.url
特性的值将从 ApiServer
bean 中动态检索。
The following example demonstrates how to use DynamicPropertyRegistry
and
@DynamicPropertySource
with a @Bean
method. The api.url
property can be accessed
via Spring’s Environment
abstraction or injected directly into other Spring-managed
components – for example, via @Value("${api.url}")
. The value of the api.url
property
will be dynamically retrieved from the ApiServer
bean.
-
Java
-
Kotlin
@Configuration
class TestConfig {
@Bean
@DynamicPropertySource
ApiServer apiServer(DynamicPropertyRegistry registry) {
ApiServer apiServer = new ApiServer();
registry.add("api.url", apiServer::getUrl);
return apiServer;
}
}
@Configuration
class TestConfig {
@Bean
@DynamicPropertySource
fun apiServer(registry: DynamicPropertyRegistry): ApiServer {
val apiServer = ApiServer()
registry.add("api.url", apiServer::getUrl)
return apiServer
}
}
在 |
The use of |
Precedence
动态特性比从 @TestPropertySource
、操作系统环境、Java 系统特性或通过使用 @PropertySource
声明性地或以编程方式由应用程序添加的特性来源加载的特性具有更高的优先级。因此,动态特性可用于选择性地覆盖通过 @TestPropertySource
、系统特性源和应用程序特性源加载的特性。
Dynamic properties have higher precedence than those loaded from @TestPropertySource
,
the operating system’s environment, Java system properties, or property sources added by
the application declaratively by using @PropertySource
or programmatically. Thus,
dynamic properties can be used to selectively override properties loaded via
@TestPropertySource
, system property sources, and application property sources.