close

@DynamicPropertySource in Spring Framework 5.2.5 and Spring Boot 2.2.6

Recently, when talking about testing Spring Boot applications at Spring IO and SpringOne Platform, I’ve mentioned Testcontainers and discussed the boilerplate involved in configuring your tests to use the service running inside the container. I’m delighted to say that, with the recent Spring Framework 5.2.5 release, that boilerplate is no more.

Prior to the changes that we’ve just released, your integration test would look similar to the following:

@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());
        }

    }

}

Here we are using @ContextConfiguration to specify an ApplicationContextInitializer. The initializer is configuring the spring.data.neo4j.uri property with the value of the Neo4j container’s bolt URL. This allows Neo4j-related beans in our application to communicate with Neo4j running inside the Testcontainers-managed Docker container.

Thanks to the changes made in Spring Framework 5.2.5, the use of @ContextConfiguration and the ApplicationContextInitializer can be replaced with a static @DynamicPropertySource method that serves the same purpose. If we make these changes to the integration test class shown above, it now looks like the following:

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }

}

We’ve reduced the amount of code by a third and the intent is hopefully much clearer as well.

While the new feature was inspired by making Testcontainers easier to use in a Spring Boot integration test, it should be useful in any Spring-based integration test where a property’s value isn’t known up front. You can learn more about @DynamicPropertySource in the Spring Framework reference documentation.

Happy integration testing!

comments powered by Disqus