TestContainers, Spring Webflux, JUnit 5, MySQLR2DBCDatabaseContainer using @DynamicPropertySource

huangapple go评论116阅读模式
英文:

TestContainers, Spring Webflux, JUnit 5, MySQLR2DBCDatabaseContainer using @DynamicPropertySource

问题

我正在尝试完成以下操作;
但是使用 org.testcontainers.containers.MySQLR2DBCDatabaseContainer
有谁能够展示我如何实现这个,因为 MySQLR2DBCDatabaseContainer 似乎没有以下方法:

  • ::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() {
  }
}
英文:

I'm trying to do the following; <br/>
but using org.testcontainers.containers.MySQLR2DBCDatabaseContainer <br />
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(&quot;inmemory&quot;)
    .withUsername(&quot;inmemory&quot;);
  @DynamicPropertySource
  static void postgresqlProperties(DynamicPropertyRegistry registry) {
    registry.add(&quot;spring.datasource.url&quot;, postgreSQLContainer::getJdbcUrl);
    registry.add(&quot;spring.datasource.password&quot;, postgreSQLContainer::getPassword);
    registry.add(&quot;spring.datasource.username&quot;, postgreSQLContainer::getUsername);
  }
  @Test
  public void contextLoads() {
  }
}

答案1

得分: 7

针对您的情况,您应该为 R2dbc 连接创建属性,而不是 Jdbc 连接。

您需要手动计算 R2dbc URL,而不是使用 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());

更简单的方法是为测试容器创建一个基于 tc 配置文件的配置。

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

URL 中的 tc 将自动启动一个 TestContainers Docker 容器。详见TestContainers R2dbc 支持

然后,您还可以通过 @TestConfiguration 来应用一些初始工作(例如创建模式和插入示例数据)。

@DataR2dbcTest
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@ActiveProfiles("tc") // 激活 `tc` 配置文件。
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;

    // 您的测试代码...

我这里有一些 TestContainers 的示例:

  1. 通过 R2dbc URL 启动容器,参见这个 R2dbc MySQL 示例

  2. 使用 Junit 进行手动设置,参见这个 R2dbc PostgreSQL 示例

  3. 使用 Spring 初始化器类来初始化容器,参见这个 Neo4j Rx 示例

英文:

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(&quot;spring.r2dbc.url&quot;, () -&gt; &quot;r2dbc:postgresql://&quot;
                + postgreSQLContainer.getHost() + &quot;:&quot; + postgreSQLContainer.getFirstMappedPort()
                + &quot;/&quot; + postgreSQLContainer.getDatabaseName());
registry.add(&quot;spring.r2dbc.username&quot;, () -&gt; postgreSQLContainer.getUsername());
registry.add(&quot;spring.r2dbc.password&quot;, () -&gt; 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(&quot;tc&quot;)// 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(&quot;schema.sql&quot;)));
            populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource(&quot;data.sql&quot;)));
            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.

答案2

得分: 0

这实际上有点棘手。如果您正在使用响应式存储库,您应该继续使用 MySQLContainer,但是您必须更改设置数据源的方式(我的代码略有不同,但我希望足够接近,以便为您提供解决问题的思路)。请注意使用了 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());
    }
}

您可以查看我的存储库;我在相同的问题上困扰了几天:UserRepositoryIntegrationTest.java

英文:

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(&quot;mysql:8.0.28&quot;);

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

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

    private static String r2dbcUrl() {
        return String.format(&quot;r2dbc:mysql://%s:%s/%s&quot;,
                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

huangapple
  • 本文由 发表于 2020年8月20日 18:00:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/63502688.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定