Я хочу иметь автоматические тесты для тестирования команд импорта из источника данных A (оракул) в источник данных B (postgres). Оба источника данных должны быть созданы с помощью тестконтейнеров.
Базовая настройка выполнена, но проблема в следующем:
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);
Я вижу, что тестконтейнеры никогда не дожидаются его завершения.
Все, что я нашел в Интернете об этой «ошибке» или «проблеме», это BugReport на github: https://github.com/testcontainers/testcontainers-java/issues/1292
И кажется, что пользователь даже использует тот же контейнер, что и я. Однако решение, упомянутое в проблеме, не сработало для меня.
2 ответа
Я решил эту проблему, создав сценарий (фактически два, но его можно объединить в один), который проверяет, существует ли пользователь базы данных «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 не истекает по умолчанию. Он просто ждет, пока все, что вы делаете, не закончится. Я обнаружил это во время отладки, и решение работает для меня.
Вы можете попробовать переопределить getTestQueryString OracleContainer
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'";
}
}
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.