如何在 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。
您可以使用 ContextConfiguration
和 ApplicationContextInitializer
.
在 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)
文档:
自从 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。
假设我想在 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。
您可以使用 ContextConfiguration
和 ApplicationContextInitializer
.
覆盖 属性 - 定义静态内部 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
:
@ContextConfiguration(initializers = Initializer.class)
文档:
自从 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。