[英]Using Testcontainers with JUnit5 extensions
I using Spring boot
and JUnit5
.我使用
Spring boot
和JUnit5
。 My app work with several databases: MySQL
, Clickhouse
, etc.我的应用程序使用多个数据库:
MySQL
、 Clickhouse
等。
For integration testing, I created JUnit5 Extensions:对于集成测试,我创建了 JUnit5 扩展:
public class ClickHouseTestContainersExtension implements BeforeAllCallback, BeforeTestExecutionCallback {
public static final String IMAGE_NAME = "registry.mycomp.com/db/clickhouse-server:20.5.3.27";
@Container
private static final FixedHostPortGenericContainer<?> clickHouse = new FixedHostPortGenericContainer<>(IMAGE_NAME)
.withCopyFileToContainer(MountableFile.forClasspathResource("dbInitScripts/init_clickhouse.sql"), "/docker-entrypoint-initdb.d/init_clickhouse.sql")
.withMinimumRunningDuration(Duration.ofSeconds(7))
.withFixedExposedPort(8124, 8123);
@Override
public void beforeAll(ExtensionContext extensionContext) {
startContainerIfNeed();
}
@Override
public void beforeTestExecution(ExtensionContext extensionContext) {
startContainerIfNeed();
}
public void startContainerIfNeed() {
if (!clickHouse.isRunning()) {
log.info("ClickHouse container is not running! Started.....");
clickHouse.start();
}
}
}
And MySQL:和 MySQL:
public class MySQLTestContainersExtension implements BeforeAllCallback, BeforeTestExecutionCallback {
private static final String IMAGE_NAME = "registry.mycomp.com/db/mariadb:10.4.11";
@Container
private static final FixedHostPortGenericContainer<?> mariaDb = new FixedHostPortGenericContainer<>(IMAGE_NAME)
.waitingFor(new LogMessageWaitStrategy()
.withRegEx(".*ready for connections.*")
.withTimes(2)
.withStartupTimeout(Duration.of(3, MINUTES)))
.withEnv("MYSQL_DATABASE", "db")
.withEnv("MYSQL_USER", "sys")
.withEnv("MYSQL_PASSWORD", "qwerty")
.withEnv("MYSQL_ROOT_PASSWORD", "toor")
.withEnv("MYSQL_RANDOM_ROOT_PASSWORD", "no")
.withEnv("MYSQL_ALLOW_EMPTY_PASSWORD", "no")
.withFixedExposedPort(33060, 3306)
.withCopyFileToContainer(MountableFile.forClasspathResource("dbInitScripts/init_mysql.sql"),
"/docker-entrypoint-initdb.d/init_mysql.sql");
@Override
public void beforeAll(ExtensionContext extensionContext) {
startContainerIfNeed();
}
@Override
public void beforeTestExecution(ExtensionContext extensionContext) {
startContainerIfNeed();
}
public void startContainerIfNeed() {
if (!mariaDb.isRunning()) {
log.info("MariaDB container is not running! Started.....");
mariaDb.start();
}
}
}
And a number of other similar extensions.以及许多其他类似的扩展。
I also have annotations:我也有注释:
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RUNTIME)
@ExtendWith({MySQLTestContainersExtension.class})
public @interface MySQL {
}
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RUNTIME)
@ExtendWith({ClickHouseTestContainersExtension.class})
public @interface ClickHouse {
}
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RUNTIME)
@ExtendWith({ClickHouseTestContainersExtension.class, MySQLTestContainersExtension.class,
PostgreSQLTestContainersExtension.class, IgniteTestContainersExtension.class})
public @interface WithAllDatabases {
}
And, When I write some test, I use this extension:而且,当我写一些测试时,我使用这个扩展:
@Test
@ClickHouse
@DisplayName("Test connection ClickHouse with alive status")
void testConnectionClickHouseWithAliveStatus() throws IOException {
//smth
}
@Test
@MySQL
@DisplayName("Test connection MySQL with alive status")
void testConnectionMariaDBWithAliveStatus() throws IOException {
//smth
}
//etc
My connections properties, like username, password, url, store in database, not in apllication.yml.我的连接属性,如用户名、密码、url,存储在数据库中,而不是在 apllication.yml 中。 Any user of my system, can mannualy add new connection.
我系统的任何用户都可以手动添加新连接。
So I can't just use a spring mechanism like a @DynamicPropertySource
.所以我不能只使用像
@DynamicPropertySource
这样的弹簧机制。
Moreover, I can't get the generated random port from the extension in any way!此外,我无法以任何方式从扩展中获取生成的随机端口!
Therefore, I use a fixed port to create a set of test connections to the database raised in the content in tests!因此,我使用固定端口创建了一组测试连接到数据库中提出的内容在测试中!
Tell me if there is some approach that will allow you to use the JUnit 5
extension and use a random port.告诉我是否有某种方法可以让您使用
JUnit 5
扩展并使用随机端口。 My task was to raise any database for a specific test by simply putting an annotation above this test.我的任务是通过简单地在此测试上方添加注释来为特定测试提升任何数据库。
I have a few questions我有几个问题
startContainerIfNeed()
into a factory method) and call MySQLTestContainersExtension.getContainer()
when you need a containerstartContainerIfNeed()
转换为工厂方法)并在需要容器时调用MySQLTestContainersExtension.getContainer()
mariaDb
variable static or make it a regular field and access via gettermariaDb
变量静态或使其成为常规字段并通过 getter 访问Also @Container
does not do anything in your case, you can read about it here此外,@
@Container
对您的情况没有任何作用,您可以在此处阅读相关信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.