Reputation: 5005
The @DynamicPropertySource
annotation was added as part of the release 5.2.5 of the Spring Framework. The official documentation says that:
This annotation and its supporting infrastructure were originally designed to allow properties from Testcontainers based tests to be exposed easily to Spring integration tests. However, this feature may also be used with any form of external resource whose lifecycle is maintained outside the test's ApplicationContext.
There is also a basic example:
@SpringJUnitConfig(...)
@Testcontainers
class ExampleIntegrationTests {
@Container
static RedisContainer redis = new RedisContainer(); // ...
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("redis.host", redis::getContainerIpAddress);
registry.add("redis.port", redis::getMappedPort);
} }
However, I don't understand... what's the use case for this new annotation when we have @PropertySource that behaves in the same way?
Upvotes: 7
Views: 9437
Reputation: 5005
I eventually found the answer in this Github issue that led to the commit for the @DynamicPropertySource
annotation.
The annotation @PropertySource
:
Is mainly used to read from property files using Spring Environment interface
Examples of its use can be found in this nice article.
@DynamicPropertySource
instead is used to:
make it easier to set configuration properties from something else that's bootstrapped as part of running an integration test.
This helps also setting up integration tests with Testcontainers, getting rid of a lot of boilerplate code.
While the documentation is lacking in this case, a very good article can be found in this blog on the spring.io website. As per the article above, examples are:
@SpringBootTest
@Testcontainers
@ContextConfiguration(initializers = ExampleIntegrationTests.Initializer.class)
class ExampleIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>();
static class Initializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
TestPropertyValues.of("spring.data.neo4j.uri=" + neo4j.getBoltUrl())
.applyTo(context.getEnvironment());
}
}
}
The @DynamicPropertySource
annotation can make the test above clearer, eliminating the boiler plate code as you can see in the example below:
@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>();
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
}
}
Upvotes: 15