1

I want to run spring integration tests with MySQLContainer in docker. I use volume for docker.sock, but have some troubles.

build.gradle:

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.5'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'org.autovill'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: '3.0.5'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-r2dbc', version: '3.0.5'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation group: 'org.flywaydb', name: 'flyway-core', version: '9.16.3'
    implementation group: 'org.flywaydb', name: 'flyway-mysql', version: '9.16.3'
    implementation group: 'io.asyncer', name: 'r2dbc-mysql', version: '1.0.0'
    implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.0.32'

    implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
    runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
    runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '3.0.5'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation group: 'io.projectreactor', name: 'reactor-test', version: '3.5.5'

    testImplementation "org.testcontainers:testcontainers:1.18.0"
    implementation platform('org.testcontainers:testcontainers-bom:1.18.0') //import bom
    testImplementation('org.testcontainers:mysql') //no version specified
}

tasks.named('test') {
    useJUnitPlatform()
}

test {
    systemProperty 'spring.profiles.active', 'test'
}

I have such Dockerfile:

FROM gradle:7.6.1-jdk17-jammy as base
WORKDIR /app
COPY ./ ./
RUN gradle dependencies

FROM base as test
CMD ["gradle", "test"]

So, in tests I create MySQLContainer and set up properties.

@SpringBootTest
class AutovillApplicationStarterTest {
    @ClassRule
    public static MySQLContainer mysql = new MySQLContainer<>("mysql:8.0")
        .withExposedPorts(3306, 3306)
        .withEnv("MYSQL_ROOT_HOST", "%")
        .withUsername("azamat")
        .withPassword("123456")
        .withDatabaseName("autovill")
        .withEnv("MYSQL_HOST", "%");

    static {
        mysql.start();

        System.out.println("MYSQL_HOST: " + mysql.getHost());
        System.out.println("MYSQL JDBC URL: " + mysql.getJdbcUrl());

        System.setProperty("spring.r2dbc.url", mysql.getJdbcUrl().replace("jdbc:", "r2dbc:"));
        System.setProperty("spring.r2dbc.username", mysql.getUsername());
        System.setProperty("spring.r2dbc.password", mysql.getPassword());

        System.setProperty("spring.flyway.url", mysql.getJdbcUrl());
        System.setProperty("spring.flyway.username", mysql.getUsername());
        System.setProperty("spring.flyway.password", mysql.getPassword());
    }

    @Test
    void contextLoads() {
    }
}

It works well If i run it directly using gradle test. But If I run it via docker, there will be some troubles:

Building image:

docker build -t spring-test --target=test . 

Runing container:

docker run \
--volume /var/run/docker.sock:/var/run/docker.sock \
-v $PWD:$PWD \
-w $PWD \
spring-test   

Tests are not passed and I got such exception:

Caused by: java.lang.IllegalStateException: Could not connect to Ryuk at 172.17.0.1:49157

I tried to use -e TESTCONTAINERS_HOST_OVERRIDE=host.docker.internal parameter for docker run. Also, I created network and use it for MySQLContainer and docker run.

Zac Anger
  • 6,983
  • 2
  • 15
  • 42
Azamatik
  • 11
  • 2
  • Hi, You are writing integrating test. can you try adding `@TestContainers` and `@Container static MySQLContainer mySQLContainer = new MySQLContainer<>(DockerImageName.parse("mysql:8.0-debian")); ` – mubeen Apr 30 '23 at 16:38
  • You are also required to add the relevant dependencies in `pom.xml` – mubeen Apr 30 '23 at 16:39
  • @mubeen Added build.gradle. I dont know how to use TestContainers and Container as annotations, because It shows me that these ones are not annotations, but classes – Azamatik Apr 30 '23 at 19:33
  • `-p` is for ["publish"](https://docs.docker.com/engine/reference/commandline/run/#publish) ... We need both to (TCP) communicate with container – xerx593 Apr 30 '23 at 20:03
  • @xerx593 Do I need open port for my gradle test container? Okay, I added EXPOSE 3306 before CMD ["gradle", "test"] and add -p 3307:3306 to docker run command. But it does not work too. – Azamatik May 01 '23 at 05:39
  • No, sorry i misunderstood/oversaw (mysql/build container...) I found this useful, esp. The "2nd" answer: https://stackoverflow.com/q/56821546/592355 – xerx593 May 01 '23 at 11:54
  • ..but once fixed this, you will also (want to) access the spring container.. – xerx593 May 01 '23 at 12:04

0 Answers0