TestContainers, Spring Webflux, JUnit 5, MySQLR2DBCDatabaseContainer using @DynamicPropertySource
Asked Answered
E

2

5

I'm trying to do the following;
but using org.testcontainers.containers.MySQLR2DBCDatabaseContainer
can anyone show me how this can be achieved, as MySQLR2DBCDatabaseContainer doesn't seem to have the following methods:

  • ::getJdbcUrl
  • ::getPassword
  • ::getUsername
@Testcontainers
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationIT {
  @Container
  public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer()
    .withPassword("inmemory")
    .withUsername("inmemory");
  @DynamicPropertySource
  static void postgresqlProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
    registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
    registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
  }
  @Test
  public void contextLoads() {
  }
}
Erotica answered 20/8, 2020 at 10:0 Comment(1)
Would "Database containers launched via R2DBC URL scheme" work for you? testcontainers.org/modules/databases/r2dbcCorgi
T
8

For your case, you should create properties to a R2dbc connection instead of the Jdbc connection.

You have to compute the R2dbc URL manually instead of the Jdbc URL.

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());

More simply you can create a tc profile based application config for testcontainers.

# src/test/resources/application-tc.properties
spring.r2dbc.url=r2dbc:tc:mysql:///databasename?TC_IMAGE_TAG=8

The tc in the url will start a testcontaienrs docker automatically. See the TestContainers R2dbc support.

Then you can also apply some some initial work(eg. create schemas and insert sample data) via a @TestConfiguration.

@DataR2dbcTest
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@ActiveProfiles("tc")// activate the `tc` profile.
public class TestcontainersPostRepositoryTest {

    @TestConfiguration
    static class TestConfig {
        @Bean
        public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {

            ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
            initializer.setConnectionFactory(connectionFactory);

            CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
            populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema.sql")));
            populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("data.sql")));
            initializer.setDatabasePopulator(populator);

            return initializer;
        }
    }

    @Autowired
    DatabaseClient client;

    @Autowired
    PostRepository posts;

//your tests...

I have some testcontainers examples.

  1. Launch Contrainer via R2dbc url, see this R2dbc MySQL example.

  2. Manual setup with Junit, see this R2dbc PostgresSQL example.

  3. Use spring initializer classes to initialize a Container, see this Neo4j Rx example.

Toddler answered 7/9, 2020 at 14:25 Comment(0)
V
0

That is actually a little bit tricky. If you're using reactive repositories you should continue using MySQLContainer, but you have to change the way you set the datasource (my code is slightly different but I hope is close enough to give you an idea of how to solve your problem). Please note the use of UserRepositoryIntegrationTest::r2dbcUrl.

@Testcontainers
@DataR2dbcTest
class UserRepositoryIntegrationTest {

    @Container
    private static MySQLContainer database = new MySQLContainer("mysql:8.0.28");

    @DynamicPropertySource
    static void registerDynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.r2dbc.url", UserRepositoryIntegrationTest::r2dbcUrl);
        registry.add("spring.r2dbc.username", database::getUsername);
        registry.add("spring.r2dbc.password", database::getPassword);

        registry.add("spring.flyway.url", database::getJdbcUrl);
        registry.add("spring.flyway.user", database::getUsername);
        registry.add("spring.flyway.password", database::getPassword);
    }

    private static String r2dbcUrl() {
        return String.format("r2dbc:mysql://%s:%s/%s",
                database.getContainerIpAddress(),
                database.getMappedPort(MySQLContainer.MYSQL_PORT),
                database.getDatabaseName());
    }
}

You can have a look at my repo; I got stuck in the same problem for days: UserRepositoryIntegrationTest.java

Vertebra answered 30/1, 2022 at 11:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.