【问题标题】:testcontainers oracle database container starts before database user is createdtestcontainers oracle 数据库容器在创建数据库用户之前启动
【发布时间】:2019-12-23 01:48:19
【问题描述】:

我想进行自动化测试,以测试从数据源 A (oracle) 到数据源 B (postgres) 的导入命令。 两个数据源都应该使用测试容器创建。

基本设置已完成,但问题是:

testcontainers oracleContainer 在 Dockerfile 中定义的入口点发生更改之前启动,以完成并创建测试所需的用户。

容器运行后,会执行一些 sql 脚本来创建表并用数据填充它们。这些脚本失败是因为脚本中提到的用户尚未创建。

testcontainers 没有等待完成设置。


我已经这样设置了容器:

        OracleContainer oracleContainer = new OracleContainer("webdizz/oracle-xe-11g-sa:latest")
            .withStartupTimeoutSeconds(10000)
            .withEnv("DATABASES", "xyz");

数据库肯定是创建的,但是经过了相当长的时间(通过永远运行测试并使用 docker exec 检查数据库来测试)

我尝试了多种方式为容器设置等待策略,例如这样:

        oracleContainer.setWaitStrategy(new LogMessageWaitStrategy().withRegEx("*.Enjoy!*"));

但它没有产生任何结果。


通过检查日志:

Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER);
    oracleContainer.followOutput(logConsumer);

我可以看到 testcontainers 永远不会等待它完成。

我在网上找到的关于这个“错误”或“问题”的所有信息都是 github 上的这个错误报告: https://github.com/testcontainers/testcontainers-java/issues/1292

似乎用户甚至使用与我相同的容器。但是问题中提到的解决方案对我不起作用。

【问题讨论】:

    标签: java oracle spring-boot automated-tests testcontainers


    【解决方案1】:

    我通过创建一个脚本(实际上是两个,但可以合二为一)解决了这个问题,该脚本检查数据库用户“XYZ”是否存在,如果存在则返回 0。

    wait_check.sh

    #!/usr/bin/env bash
    while :
    do
        echo "waiting for user to exist"
        if $(/bin/bash /check_db_user.sh | grep -q XYZ); then
            echo "user XYZ exists"
            exit 0
        fi
    done
    

    check_db_user.sh

    #!/usr/bin/env bash
    sqlplus -s /nolog <<EOF
    connect username/password
    select username from dba_users where username = 'XYZ';
    quit
    EOF
    

    然后我运行 wait_check.sh

    oracleContainer.copyFileToContainer(
            MountableFile.forClasspathResource("/helper/wait_check.sh"),
            "/wait_check.sh");
    oracleContainer.copyFileToContainer(
            MountableFile.forClasspathResource("/helper/check_db_user.sh"),
            "/check_db_user.sh");
    
    try {
        Container.ExecResult result = oracleContainer.execInContainer("./wait_check.sh");
        log.debug(result.getStdout());
    } catch (IOException | InterruptedException e) {
        log.error(e.getMessage());
    }
    

    这是因为 oracleContainer.execInContainer 默认不会超时。它只是等到你所做的一切完成。 我在调试时发现了这一点,该解决方案对我有用。

    【讨论】:

      【解决方案2】:

      您可以尝试覆盖 OracleContainer 的 getTestQueryString

      OracleContainer oracleContainer = new MyOracleContainer("webdizz/oracle-xe-11g-sa:latest")
      
      ...
      
      public static class MyOracleContainer extends OracleContainer {
          public MyOracleContainer(String dockerImageName) {
              super(dockerImageName);
          }
      
          @Override
          public String getTestQueryString() {
              return "SELECT username FROM dba_users WHERE username = 'XYZ'";
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-06-26
        • 1970-01-01
        • 1970-01-01
        • 2019-09-16
        • 1970-01-01
        • 2017-08-12
        • 1970-01-01
        • 1970-01-01
        • 2011-10-07
        相关资源
        最近更新 更多