Использование собственного docker-образа БД с Testcontainers - PullRequest
0 голосов
/ 24 октября 2018

Я новичок в тестконтейнерах, поэтому у меня есть вопрос.У меня есть приложение на Spring / Hibernate.У меня есть Docker-образ (h2testbase) с MySQL база (myTestDb) с данными.Я запускаю этот образ в докере с -p 6161: 3306.В каталоге test / resources у меня есть файл application.properties.Он содержит следующий

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:6161/myTestDb?allowPublicKeyRetrieval=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Europe/Moscow&&useSSL=false
jdbc.username=root
jdbc.cred=admin
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true

Я использую mvn test - он работает.Теперь я хочу запустить эти тесты с Testcontainers.Я добавил в pom.xml зависимости

<dependency>
   <groupId>org.testcontainers</groupId>
   <artifactId>testcontainers</artifactId>
   <version>1.9.1</version>
</dependency>

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>mysql</artifactId>
    <version>1.9.1</version>
    <scope>test</scope>
</dependency>

Я расширил класс MySQLContainer

public class TestMySQL extends MySQLContainer {

    public TestMySQL() {
        super();
    }

    public TestMySQL(String dockerImageName) {
        super(dockerImageName);
    }

    @Override
    public String getDriverClassName() {
        return "com.mysql.cj.jdbc.Driver";
    }
}

cuz MySQLContainer, используя com.mysql.jdbc.Driver, и он устарел.Мой тест (например)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        HibernateConfiguration.class,
        SecurityConfiguration.class,
        SecurityInitializer.class,
        ViewConfiguration.class,
        ViewInitializer.class})
@WebAppConfiguration
public class ControllerServiceJTest {

    @ClassRule
    public static TestMySQL  container
            = new TestMySQL("h2testbase");

    @Autowired
    ControllerService controllerService;

    @Test
    public void stationPagination() {
        Map<String, Object> pag = controllerService.stationPagination(4);
        Assert.assertTrue(((List<Station>)pag.get("stations")).size() == 8);
    }

    @Test
    public void trainPagination() {
        Map<String, Object> pag = controllerService.trainPagination(1);
        Assert.assertTrue(((List<Train>)pag.get("trains")).size() == 20);
    }

    @Test
    public void switchHelper() {
        Assert.assertTrue(controllerService.stationSwitchHelper("BLUE").equals(URLs.REDIRECT_DASHSTATION + "/2"));
    }
}

И вот я бью стену.Если я использую mvn test, я вижу (через docker ps), что контейнер запущен.Он запускался два или три раза (и отображение выполнялось на случайных портах, таких как 328xx), но затем maven сообщает

org.testcontainers.containers.ContainerLaunchException: Container startup failed
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
Caused by: org.rnorth.ducttape.TimeoutException: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
Caused by: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
Caused by: java.util.concurrent.TimeoutException

Что мне теперь делать?Как подсказать моему тестконтейнеру нужный порт (6161)?Как использовать параметры, которые в application.properties?Я не могу найти примеры кода, где используются пользовательские изображения с БД с данными.Заранее спасибо

Обновление Добавление полного результата для неудачного теста.

[INFO] -------------------------------------------------------

    [INFO]  T E S T S
    [INFO] -------------------------------------------------------
    [INFO] Running ru.javasch.metro.junit.ControllerServiceJTest
    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
    SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
    SLF4J: Defaulting to no-operation MDCAdapter implementation.
    SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
            ?? Checking the system...
            ? Docker version should be at least 1.6.0
            ? Docker environment should have more than 2GB free disk space
    [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 97.189 s <<< FAILURE! - in ru.javasch.metro.junit.ControllerServiceJTest
    [ERROR] ru.javasch.metro.junit.ControllerServiceJTest  Time elapsed: 97.187 s  <<< ERROR!
    org.testcontainers.containers.ContainerLaunchException: Container startup failed
    Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
    Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
    Caused by: org.rnorth.ducttape.TimeoutException: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
    Caused by: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
    Caused by: java.util.concurrent.TimeoutException

Там немного информации.Я пробовал тесты с MySqlContainer из здесь (с моим TestMySql).Когда я использую чистое изображение mysql: 5.5 - все хорошо.Но когда я пытаюсь добавить некоторые модификации в контейнер (например, addFixedExposedPort), он не запускается, потому что порт уже выделен.В случае, когда я добавляю данные из скрипта - это «Не удалось создать контейнер».Если я пытаюсь дать ему свое изображение (h2testbase), снова «Не удалось создать контейнер».

1 Ответ

0 голосов
/ 24 октября 2018

Кажется, у вас здесь две проблемы.

  1. Docker выставляет сервер mysql на произвольный порт, но вам нужен фиксированный порт.Чтобы исправить это, вы можете установить фиксированный порт, используя addFixedExposedPort из GenericContainer

    public class TestMySQL extends MySQLContainer {
    
        public TestMySQL(String dockerImageName) {
            super(dockerImageName);
            addFixedExposedPort(6161, MYSQL_PORT);
        }
    
        @Override
        public String getDriverClassName() {
            return "com.mysql.cj.jdbc.Driver";
        }
    }
    
  2. Возможно, у вас нет базы данных test, пользователь test с паролем test в качестве учетных данных по умолчанию в MySQLContainer , которые вызывают ContainerLaunchException, который вы получаете.Используйте withDatabaseName, withUsername и withPassword для правильной настройки БД и пользователя.

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {
        HibernateConfiguration.class,
        SecurityConfiguration.class,
        SecurityInitializer.class,
        ViewConfiguration.class,
        ViewInitializer.class})
    @WebAppConfiguration
    public class ControllerServiceJTest {
    
        @ClassRule
        public static TestMySQL  container
            = new TestMySQL("h2testbase")
              .withDatabaseName("myTestDb")
              .withUsername("root")
              .withPassword("admin");
    
        @Autowired
        ControllerService controllerService;
    
        @Test
        public void stationPagination() {
            Map<String, Object> pag = controllerService.stationPagination(4);
            Assert.assertTrue(((List<Station>)pag.get("stations")).size() == 8);
        }
    
        @Test
        public void trainPagination() {
            Map<String, Object> pag = controllerService.trainPagination(1);
            Assert.assertTrue(((List<Train>)pag.get("trains")).size() == 20);
        }
    
        @Test
        public void switchHelper() {
            Assert.assertTrue(controllerService.stationSwitchHelper("BLUE").equals(URLs.REDIRECT_DASHSTATION + "/2"));
        }
    }
    

ОБНОВЛЕНИЕ :

Поворотпри ведении журнала добавьте следующую зависимость к pom.xml

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.1</version>
    </dependency>

и создайте src/test/resources/logback.xml со следующим содержанием

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>

    <logger name="org.testcontainers" level="DEBUG"/>
</configuration
...