3

Currently, I want to create an integration test for my system. I'm using testcontainers to spawn my temporary database instance, and use R2DBC Database to make my system reactive. The problem is I don't know how to create a schema in R2DBC testcontainer instance, there's clear difference in the documentation between R2DBC support and JDBC support in testcontainers web page. In JDBC, there're section to create schema after we replace JDBC URL, meanwhile in R2DBC there isn't any mention about schema creation after we replace R2DBC URL. I've tried and explored the method in PostgreSQLR2DBCDatabaseContainer, but it didn't work.

I'm also use spring boot for our system's framework, and usually I replace the URL using ContextConfiguration initializer. Is there any way to create a schema after I replace the URL for R2DBC?

ktvktv
  • 143
  • 1
  • 2
  • 7

1 Answers1

6

You have the following options to achieve what you want:

  1. Use an init script.
  2. Use an init function.
  3. Use the singleton pattern with some migration tools, such as flyway or liquibase, etc.

If you're using Spring Boot, here an article showing its use with the singleton pattern: https://rieckpil.de/reuse-containers-with-testcontainers-for-fast-integration-tests/.

For the singleton container approach you should do something similar to this:

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);
  }
}
brneto
  • 146
  • 1
  • 2
  • From what I see, the datasource url replaced by jdbc url. If the main properties is using r2dbc url, will there be an error? – ktvktv Aug 04 '21 at 15:18
  • I updated the code example to include R2DBC connection for clarification. Please see above the `R2DBC DataSource Example` new section. – brneto Aug 05 '21 at 12:26