2

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

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.

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

我正在使用 Spring Boot 2.x。

4

2 回答 2

4

从 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);
    }

}

您可以在此处阅读有关此新功能的更多信息。我还在专门的 Testcontainers 指南中介绍了不同的应用程序属性设置方式(取决于 Spring Boot 和 JUnit 版本) 。

于 2020-04-16T06:34:25.340 回答
2

您可以使用ContextConfiguration和手动覆盖 Spring-boot 测试中的属性ApplicationContextInitializer

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

  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

上下文配置

于 2019-05-03T19:19:29.440 回答