testcontainers oracle 数据库容器在创建数据库用户之前启动
testcontainers oracle database container starts before database user is created
我想进行自动化测试,以测试从数据源 A (oracle) 到数据源 B (postgres) 的导入命令。
两个数据源都应使用 testcontainers 创建。
基本设置已完成,但问题是:
testcontainers oracleContainer 在 Dokerfile 中定义的入口点发生更改以完成并创建测试所需的用户之前启动。
在容器 运行 之后,执行一些 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 从不等待它完成。
我在网上找到的关于 "bug" 或 "problem" 的所有信息都是 github 上的错误报告:
https://github.com/testcontainers/testcontainers-java/issues/1292
似乎用户甚至使用与我相同的容器。但是问题中提到的解决方案对我不起作用。
我通过创建一个脚本(实际上是两个,但可以放在一个中)来解决这个问题,该脚本检查数据库用户 "XYZ" 是否存在,如果存在则 returns 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 默认情况下不会超时。它只是等到你所做的一切完成。
我在调试时发现了这一点,该解决方案对我有用。
您可以尝试覆盖 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'";
}
}
我想进行自动化测试,以测试从数据源 A (oracle) 到数据源 B (postgres) 的导入命令。 两个数据源都应使用 testcontainers 创建。
基本设置已完成,但问题是:
testcontainers oracleContainer 在 Dokerfile 中定义的入口点发生更改以完成并创建测试所需的用户之前启动。
在容器 运行 之后,执行一些 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 从不等待它完成。
我在网上找到的关于 "bug" 或 "problem" 的所有信息都是 github 上的错误报告: https://github.com/testcontainers/testcontainers-java/issues/1292
似乎用户甚至使用与我相同的容器。但是问题中提到的解决方案对我不起作用。
我通过创建一个脚本(实际上是两个,但可以放在一个中)来解决这个问题,该脚本检查数据库用户 "XYZ" 是否存在,如果存在则 returns 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 默认情况下不会超时。它只是等到你所做的一切完成。 我在调试时发现了这一点,该解决方案对我有用。
您可以尝试覆盖 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'";
}
}