简体   繁体   中英

How to overwrite ports defined in application.properties in integration tests after testcontainer started?

Assume I want to integration test code relying on a JPA datasource in a Spring Boot 2.x application with a PostgreSQL testcontainer (great tool for managing Docker containers from within test classes with one or few more lines of code). Assume further that I'm managing the ports (included in the JDBC URL) in application.properties , eg

spring.datasource.url=jdbc:postgresql://user-service-postgres:5432/user_service

In the integration test I create testcontainers with

@Rule
PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer();

In a preparation method I can access the value I want to set for spring.datasource.url with

postgreSQLContainer.getJdbcUrl()

How to tell Spring Boot in the test to use that URL instead of the one specified in application.properties .

I'd like to stick to my property files in order to minimize changes, but I'm thankful for other approaches including an explanation why they're superior or necessary as well.

I'm using Spring Boot 2.x.

Since Spring Framework 5.2.5 (Spring Boot 2.2.6) this setup is now even simpler as we can use the @DynamicPropertySource annotation and don't have to write and register a custom initializer.

Assuming you use the JUnit 5 dependency of Testcontainers, your test can look like the following:

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer();

    @DynamicPropertySource
    static void dataSourceProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
    }

}

You can read more about this new feature here . I've also covered the different application properties setup ways (depending on Spring Boot and JUnit version) in a dedicated Testcontainers guide .

You can manually override the property from within your Spring-boot test by using ContextConfiguration and ApplicationContextInitializer .

Override the property - define a static inner class:

  static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
      TestPropertyValues
          .of("spring.datasource.url=" + postgreSQLContainer.getJdbcUrl())
          .applyTo(configurableApplicationContext.getEnvironment());
    }
  }

ApplicationContextInitializer can be used for programmatically initializing a Spring context before context refresh. Now, wire up the context initializer class by annotating at test class level with ContextConfiguration :

@ContextConfiguration(initializers = Initializer.class)

Docs:

ApplicationContextInitializer

ContextConfiguration

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM