我们如何在 Testcontainers R2DBC 中初始化架构?

How do we initialize schema in Testcontainers R2DBC?

目前,我想为我的系统创建一个集成测试。我正在使用 testcontainers 生成我的临时数据库实例,并使用 R2DBC 数据库使我的系统具有反应性。问题是我不知道如何在 R2DBC testcontainer 实例中创建模式,在 testcontainers 网页中 R2DBC support and JDBC 支持之间的文档中存在明显差异。在JDBC中,我们替换JDBCURL后,有创建模式的部分,而在R2DBC中,我们没有提及在我们替换R2DBCURL后创建模式。 PostgreSQLR2DBCDatabaseContainer中的方法我已经尝试和探索了,但是没有用。

我也为我们的系统框架使用 spring 引导,通常我使用 ContextConfiguration 初始化程序替换 URL。在我为 R2DBC 替换 URL 之后,有什么方法可以创建模式吗?

您有以下选择来实现您想要的:

  1. 使用 init script.
  2. 使用 init function.
  3. 使用singleton pattern with some migration tools, such as flyway or liquibase

如果您正在使用 Spring Boot, here an article showing its use with the singleton pattern: https://rieckpil.de/reuse-containers-with-testcontainers-for-fast-integration-tests/

对于 singleton container approach 你应该做类似的事情:

public abstract class PostgresTestContainer {
           
  private final PostgreSQLContainer<?> postgresContainer =
                         new PostgreSQLContainer<>("postgres:13.3-alpine")
                                 .withDatabaseName("foo")
                                 .withUsername("foo")
                                 .withPassword("secret");

  static {
    postgresContainer.start();
  }

  @DynamicPropertySource
  private static void setDatasourceProperties(DynamicPropertyRegistry registry) {

    // JDBC DataSource Example
    registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
    registry.add("spring.datasource.password", postgresContainer::getPassword);
    registry.add("spring.datasource.username", postgresContainer::getUsername);

    // R2DBC DataSource Example
    registry.add("spring.r2dbc.url", () ->
            format("r2dbc:pool:postgresql://%s:%d/%s",
                        postgresContainer.getHost(),
                        postgresContainer.getFirstMappedPort(),
                        postgresContainer.getDatabaseName()));
    registry.add("spring.r2dbc.username", postgresContainer::getUsername);
    registry.add("spring.r2dbc.password", postgresContainer::getPassword);
  }
}