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

Posted

技术标签:

【中文标题】testcontainer启动后如何覆盖集成测试中application.properties中定义的端口?【英文标题】:How to overwrite ports defined in application.properties in integration tests after testcontainer started? 【发布时间】:2019-09-22 08:29:38 【问题描述】:

假设我想在 Spring Boot 2.x 应用程序中使用 PostgreSQL testcontainer(用于通过一行或几行代码从测试类中管理 Docker 容器的好工具)集成测试代码,该代码依赖于 Spring Boot 2.x 应用程序。进一步假设我正在管理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 Boot 使用该 URL 而不是 application.properties 中指定的 URL。

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

我正在使用 Spring Boot 2.x。

【问题讨论】:

【参考方案1】:

您可以使用 ContextConfigurationApplicationContextInitializer 在 Spring-boot 测试中手动覆盖该属性。

覆盖属性 - 定义一个静态内部类:

  static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> 

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

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

@ContextConfiguration(initializers = Initializer.class)

文档:

ApplicationContextInitializer

ContextConfiguration

【讨论】:

但是,问题是。在 Testcontainers 中运行 Postgresql 时更改端口 и 问题仍然存在。 不,这不是 OP 的问题,他们也接受了这个答案。我不明白它是如何仍然开放的。正如我在这里看到的那样,您的问题有所不同 - ***.com/questions/69132686/…。我敦促您继续讨论。【参考方案2】:

自 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。我还在dedicated Testcontainers guide 中介绍了不同的应用程序属性设置方式(取决于 Spring Boot 和 JUnit 版本)。

【讨论】:

但是,问题是。在 Testcontainers 中运行 Postgresql 时更改端口 и 问题仍然悬而未决 我不这么看这个问题。为什么要更改正在运行的容器的端口? 提前在IntelliJ idea中配置数据库管理器,不要每次都改变端口,因为它是动态分配的。这很不方便。 我可以看到您对这个问题有一个未解决的问题 (***.com/questions/69132686/…) - 我想最好在那里继续讨论 我还没有收到答复

以上是关于testcontainer启动后如何覆盖集成测试中application.properties中定义的端口?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Testcontainers + Quarkus + MongoDB 进行集成测试

如何使用 TestContainers 创建 apache spark 独立集群以进行集成测试?

在 Spring Boot 集成测试中使用 TestContainer 填充数据库

为啥 testcontainers 在测试类之间重启容器

如何使用 Junit 5 使用 Testcontainer 对 Kafka 运行集成测试

Testcontainers - 在实例化过程中不要自动启动容器