首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用带有JUnit5扩展的测试容器

使用带有JUnit5扩展的测试容器
EN

Stack Overflow用户
提问于 2020-11-24 17:32:09
回答 1查看 483关注 0票数 0

我使用Spring bootJUnit5。我的应用程序可以使用几个数据库:MySQLClickhouse等。

为了进行集成测试,我创建了JUnit5扩展:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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();
        }
    }
}

以及许多其他类似的扩展。

我也有注解:

代码语言:javascript
复制
@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 {
}

并且,当我编写一些测试时,我使用这个扩展:

代码语言:javascript
复制
    @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扩展并使用随机端口。我的任务是通过简单地将注释放在此测试之上来为特定测试引发任何数据库。

EN

回答 1

Stack Overflow用户

发布于 2020-11-25 22:02:54

我有几个问题

  1. 可以工作吗?你只是想使用随机的端口而不是固定的端口,或者它根本不工作?
  2. 我认为你太严格地遵循了要求。仅仅简单地在测试类/方法上放置一个注释并不是最终目的,因为您没有API来处理您的代码。据我所知,您不能访问扩展类中的任何内容(字段、方法)。我相信您可能会发现,为每个数据库容器创建一个单独的工厂会更方便(将startContainerIfNeed()转换为工厂方法),并在需要容器
  3. 时调用MySQLTestContainersExtension.getContainer(),或者在扩展类之外创建一个抽象类并在测试类中扩展它,在这种情况下,您可以保持mariaDb变量为静态变量,或者使其成为常规字段并通过

进行访问

此外,@Container在您的情况下不做任何事情,您可以在here中阅读有关它的内容

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64983684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档