Context Configuration with Dynamic Property Sources
As of Spring Framework 5.2.5, the TestContext framework provides support for dynamic
properties via the @DynamicPropertySource
annotation. This annotation can be used in
integration tests that need to add properties with dynamic values to the set of
PropertySources
in the Environment
for the ApplicationContext
loaded for the
integration test.
The |
In contrast to the @TestPropertySource
annotation that is applied at the class level, @DynamicPropertySource
must be applied
to a static
method that accepts a single DynamicPropertyRegistry
argument which 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, as can be seen in the following example which 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.
If you use |
-
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 ...
}
Precedence
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.