Automatically launch docker-compose from Gradle for dev and integration tests

Creating fresh Spring Boot application.

Building Integration Tests

  1. Write the tests
  2. Configure Gradle to run them
  3. Configure Gradle to launch the backend automatically for the integration tests.
  4. Run the tests

Step 1: Writing the integration tests

spring:
neo4j:
uri: "bolt://localhost:8687"
authentication:
username: neo4j
password: password

Step 2: Configure Gradle to the integration tests

sourceSets {
integrationTest {
java {
srcDir "src/integration/java"
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
}
resources.srcDir file("src/integration/resources")
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
integrationTestImplementation.extendsFrom implementation
integrationTestImplementation.extendsFrom testImplementation
integrationTestRuntime.extendsFrom testRuntime
}
task integrationTest(type: Test) {
group 'Test'
useJUnitPlatform()
mustRunAfter test
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}

Step 3: Integrating docker-compose

version: '3'
services:
neo4j:
image: neo4j:4.2.5
hostname: neo4j
container_name: neo4j
ports:
- "8474:7474"
- "8687:7687"
environment:
NEO4J_AUTH: neo4j/password
NEO4J_dbms_memory_heap_max__size: 256M
NEO4J_dbms_logs_debug_level: DEBUG
plugins {
id 'org.springframework.boot' version '2.4.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'idea'
id 'com.avast.gradle.docker-compose' version "0.14.2"
}
dockerCompose {
integration {
// Define the docker compose file for integration testing
useComposeFiles = ["${buildDir}/resources/integrationTest/docker-compose.yml"]
isRequiredBy(integrationTest)
}
}

Step 4: Running the integration tests

Running docker-compose for dev

version: '3'
services:
neo4j:
image: neo4j:4.2.5
hostname: neo4j
container_name: neo4j
ports:
- "7474:7474"
- "7687:7687"
environment:
NEO4J_AUTH: neo4j/password
NEO4J_dbms_memory_heap_max__size: 256M
NEO4J_dbms_logs_debug_level: DEBUG
dockerCompose {
dev {
// Specify that bootRun depends on dockerCompose
useComposeFiles = ["${buildDir}/resources/main/docker-compose.yml"]
isRequiredBy(bootRun)
}
integration {
// Define the docker compose file for integration testing
useComposeFiles = ["${buildDir}/resources/integrationTest/docker-compose.yml"]
isRequiredBy(integrationTest)
}
}

Limitations and room for improvements

  1. I fixed the expose ports for Neo4j. This is not good practice! Especially if your CI/CD system is running multiple tests on different branches at the same time. The gradle-docker-compose-plugin can randomly assign ports to avoid conflict, then you can read them as environment variables in your tests. I was just lazy to do so for this blogpost 🙈
  2. Testcontainers provides an alternative approach to this method and integrates more into your java tests. I’ve not explored that project in detail yet.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store