我使用Spring boot和JUnit5。我的应用程序可以使用几个数据库:MySQL、Clickhouse等。
为了进行集成测试,我创建了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();
}
}
}和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();
}
}
}以及许多其他类似的扩展。
我也有注解:
@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 {
}并且,当我编写一些测试时,我使用这个扩展:
@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我的连接属性,如用户名、密码、url、存储在数据库中,而不是apllication.yml中。我的系统的任何用户都可以手动添加新的连接。
所以我不能仅仅使用像@DynamicPropertySource这样的弹簧装置。
此外,我无法以任何方式从扩展中获取生成的随机端口!
因此,我使用固定端口来创建一组到测试内容中提出的数据库的测试连接!
告诉我是否有什么方法可以让您使用JUnit 5扩展并使用随机端口。我的任务是通过简单地将注释放在此测试之上来为特定测试引发任何数据库。
发布于 2020-11-25 22:02:54
我有几个问题
startContainerIfNeed()转换为工厂方法),并在需要容器MySQLTestContainersExtension.getContainer(),或者在扩展类之外创建一个抽象类并在测试类中扩展它,在这种情况下,您可以保持mariaDb变量为静态变量,或者使其成为常规字段并通过进行访问
此外,@Container在您的情况下不做任何事情,您可以在here中阅读有关它的内容
https://stackoverflow.com/questions/64983684
复制相似问题