如何在 testcontainer 启动后覆盖集成测试中 application.properties 中定义的端口?

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

假设我想在 Spring Boot 2.x 应用程序中集成依赖于 JPA 数据源的测试代码和 PostgreSQL testcontainer(管理 Docker 容器的好工具从测试 类 中使用一行或几行代码)。进一步假设我正在管理 application.properties 中的端口(包含在 JDBC URL 中),例如

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

在集成测试中,我使用

创建了测试容器
@Rule
PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer();

在准备方法中,我可以使用

访问我想为spring.datasource.url设置的值
postgreSQLContainer.getJdbcUrl()

如何告诉 Spring 在测试中引导使用 URL 而不是 application.properties 中指定的那个。

我想坚持使用我的 属性 文件以尽量减少更改,但我很感谢其他方法,包括解释为什么它们更优越或必要。

我正在使用 Spring 启动 2.x。

您可以使用 ContextConfigurationApplicationContextInitializer.

在 Spring- 引导测试中手动覆盖 属性

覆盖 属性 - 定义静态内部 class:

  static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

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

ApplicationContextInitializer 可用于在上下文刷新之前以编程方式初始化 Spring 上下文。现在,通过在测试 class 级别注释 ContextConfiguration:

来连接上下文初始值设定项 class
@ContextConfiguration(initializers = Initializer.class)

文档:

ApplicationContextInitializer

ContextConfiguration

自从 Spring Framework 5.2.5 (Spring Boot 2.2.6) 以来,这个设置现在变得更加简单,因为我们可以使用 @DynamicPropertySource 注释而不必编写并注册一个自定义初始化器。

假设您使用 Testcontainers 的 JUnit 5 依赖项,您的测试可能如下所示:

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer();

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

}

您可以阅读有关此新功能的更多信息here. I've also covered the different application properties setup ways (depending on Spring Boot and JUnit version) in a dedicated Testcontainers guide