Integration Testing Java with Docker: A Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Integration Testing Java with Docker: From A to Z

\n\n

Integration testing is a key development stage that allows you to verify the interaction of application components with external systems: databases, message queues, REST services. The traditional approach using H2 or embedded servers often leads to discrepancies between the test and production environments. The solution is Docker. In this article, we will break down how to set up integration testing for Java applications with Docker using the Testcontainers library and Docker Compose. You will learn how to write tests that work with real containers and how to integrate them into CI/CD.

\n\n

Why Docker for Integration Tests?

\n

Docker allows you to spin up isolated containers with exact versions of dependencies (PostgreSQL, Redis, Kafka) right before tests and destroy them afterwards. This guarantees:

\n
    \n
  • Production parity — you test with a real database, not an emulation.
  • \n
  • Isolation — each test run starts from a clean state.
  • \n
  • Parallel execution — multiple test classes can use different containers.
  • \n
  • Reproducibility — tests work the same way on a local machine and in CI.
  • \n
\n\n

Project Setup with Testcontainers

\n

Testcontainers is a Java library that manages the lifecycle of Docker containers. Let's add the dependency to pom.xml (Maven):

\n
<dependency>\n    <groupId>org.testcontainers</groupId>\n    <artifactId>testcontainers</artifactId>\n    <version>1.19.3</version>\n    <scope>test</scope>\n</dependency>\n<dependency>\n    <groupId>org.testcontainers</groupId>\n    <artifactId>postgresql</artifactId>\n    <version>1.19.3</version>\n    <scope>test</scope>\n</dependency>\n<dependency>\n    <groupId>org.springframework.boot</groupId>\n    <artifactId>spring-boot-starter-test</artifactId>\n    <scope>test</scope>\n</dependency>
\n\n

For Gradle, add to build.gradle:

\n
testImplementation 'org.testcontainers:testcontainers:1.19.3'\ntestImplementation 'org.testcontainers:postgresql:1.19.3'
\n\n

Example: Testing a Repository with PostgreSQL

\n

Let's consider a simple service for working with users. We'll create a test that spins up a PostgreSQL container and checks data persistence.

\n\n
import org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.DynamicPropertyRegistry;\nimport org.springframework.test.context.DynamicPropertySource;\nimport org.testcontainers.containers.PostgreSQLContainer;\nimport org.testcontainers.junit.jupiter.Container;\nimport org.testcontainers.junit.jupiter.Testcontainers;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n@Testcontainers\n@SpringBootTest\nclass UserRepositoryTest {\n\n    @Container\n    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")\n            .withDatabaseName("testdb")\n            .withUsername("test")\n            .withPassword("test");\n\n    @DynamicPropertySource\n    static void configureProperties(DynamicPropertyRegistry registry) {\n        registry.add("spring.datasource.url", postgres::getJdbcUrl);\n        registry.add("spring.datasource.username", postgres::getUsername);\n        registry.add("spring.datasource.password", postgres::getPassword);\n    }\n\n    @Autowired\n    private UserRepository userRepository;\n\n    @Test\n    void shouldSaveAndFindUser() {\n        User user = new User("john_doe", "john@example                

Blogs

Book Recommendations