英文:
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("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() {
}
}
答案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 的示例:
-
通过 R2dbc URL 启动容器,参见这个 R2dbc MySQL 示例。
-
使用 Junit 进行手动设置,参见这个 R2dbc PostgreSQL 示例。
-
使用 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("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.
-
Launch Contrainer via R2dbc url, see this R2dbc MySQL example.
-
Manual setup with Junit, see this R2dbc PostgresSQL example.
-
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("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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论