如何使用两个不同的驱动程序重用 `testcontainers` 容器?

How to reuse a `testcontainers` container with two different drivers?

我在同一个应用程序中同时使用 r2dbc 和 Liquibase。但是,Liquibase 无法使用 r2dbc 运行 迁移,因此我需要使用单独的 jdbc 驱动程序。

我遵循解决方案 ,并使用 testcontainers 进行测试,所以我的 application-test.yaml 看起来完全像这样:

spring:
  liquibase:
    url: jdbc:tc:postgresql:14.1:///testdb
  r2dbc:
    url: r2dbc:tc:postgresql:///testdb?TC_IMAGE_TAG=14.1

这非常有效,启动了迁移,然后查询就可以 运行。问题是,这启动了两个不同的容器!因此迁移 运行 针对其中一个,而查询针对另一个,因此他们发现数据库是空的。

有什么方法可以告诉 testcontainers 对两个连接使用相同的容器。

当您使用 Testcontainers 的 JDBC support 时,您可以通过在 jdbc url 中添加 tc 来配置它,容器的生命周期是自动管理的。 因为你有两个不同的 urls 像这样检测,你得到 2 个容器。

相反,您可以选择一种不同的方式来管理生命周期,让您拥有更多的控制权。

您可以 do it yourself by creating a containers instances and calling start()/stop() or for example use JUnit integration 将容器生命周期与测试生命周期相对应。

例如,对于 JUnit5,您将 class 标记为 @Testcontainers,字段标记为 @Container,例如:

@Testcontainers
class MixedLifecycleTests {
    @Container
    private static PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer();
}

由于您正在开发 Spring 应用程序,因此您希望将其配置为使用容器,为此用途 @DynamicPropertySourcehttps://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/context/DynamicPropertySource.html

简而言之,您用它标记一个方法并在其中配置 Spring 以使用容器中的数据库:

@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
  registry.add("spring.datasource.url", postgresqlContainer:: getJdbcUrl);
  registry.add("spring.datasource.username", postgresqlContainer::getUsername);
  registry.add("spring.datasource.password", postgresqlContainer::getPassword);

  registry.add("spring.r2dbc.url", () -> "r2dbc:postgresql://"
                + postgreSQLContainer.getHost() + ":" + postgreSQLContainer.getFirstMappedPort()
                + "/" + postgreSQLContainer.getDatabaseName());
  registry.add("spring.r2dbc.username", postgreSQLContainer::getUsername);
  registry.add("spring.r2dbc.password", postgreSQLContainer::getPassword);
}

请注意,由于您的应用使用 r2dbc 而 Liquibase 与 non-reactive jdbc 一起使用,因此您应该同时配置两者。