使用 @DynamicPropertySource 的 TestContainers、Spring Webflux、JUnit 5、MySQLR2DBCDatabaseContainer

Posted

技术标签:

【中文标题】使用 @DynamicPropertySource 的 TestContainers、Spring Webflux、JUnit 5、MySQLR2DBCDatabaseContainer【英文标题】:TestContainers, Spring Webflux, JUnit 5, MySQLR2DBCDatabaseContainer using @DynamicPropertySource 【发布时间】:2020-12-09 15:35:17 【问题描述】:

我正在尝试执行以下操作; 但使用 org.testcontainers.containers.MySQLR2DBCDatabaseContainer 谁能告诉我这是如何实现的,因为 mysqlR2DBCDatabaseContainer 似乎没有以下方法:

::getJdbcUrl ::getPassword ::获取用户名
@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() 
  

【问题讨论】:

“通过 R2DBC URL 方案启动的数据库容器”对您有用吗? testcontainers.org/modules/databases/r2dbc 【参考方案1】:

对于您的情况,您应该为 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会自动启动一个testcontaienrs docker。请参阅TestContainers R2dbc support。

然后您还可以通过@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...

我有一些测试容器示例。

    通过 R2dbc url 启动 Contrainer,请参阅 this R2dbc MySQL example。

    使用 Junit 手动设置,请参阅 this R2dbc PostgresSQL example。

    使用spring初始化器类来初始化一个Container,见this Neo4j Rx example。

【讨论】:

【参考方案2】:

这实际上有点棘手。如果您使用的是响应式存储库,您应该继续使用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

【讨论】:

以上是关于使用 @DynamicPropertySource 的 TestContainers、Spring Webflux、JUnit 5、MySQLR2DBCDatabaseContainer的主要内容,如果未能解决你的问题,请参考以下文章

无法连接到 SpringTest 中由 TestContainers 创建的容器

测试使用

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)