How to Use Testcontainers with JUnit for Integration Testing
Use
Testcontainers with JUnit by adding the @Testcontainers annotation to your test class and defining container fields with @Container. Start containers automatically during tests to provide real services like databases, ensuring isolated and repeatable integration tests.Syntax
To use Testcontainers with JUnit, annotate your test class with @Testcontainers. Define container fields with @Container to manage lifecycle automatically. Use container methods to get connection info for your tests.
@Testcontainers: Enables Testcontainers support in JUnit tests.@Container: Marks a container field to be started and stopped automatically.- Container classes like
PostgreSQLContainerrepresent Docker containers for services.
java
import org.junit.jupiter.api.Test; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.containers.PostgreSQLContainer; @Testcontainers public class MyDatabaseTest { @Container public PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.2") .withDatabaseName("testdb") .withUsername("user") .withPassword("pass"); @Test void testConnection() { String url = postgres.getJdbcUrl(); String user = postgres.getUsername(); String pass = postgres.getPassword(); // Use these to connect and test } }
Example
This example shows a JUnit 5 test using Testcontainers to start a PostgreSQL container. The test connects to the database and verifies a simple query.
java
import org.junit.jupiter.api.Test; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import static org.junit.jupiter.api.Assertions.assertEquals; @Testcontainers public class PostgresTest { @Container public PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.2") .withDatabaseName("testdb") .withUsername("user") .withPassword("pass"); @Test void testSimpleQuery() throws Exception { String url = postgres.getJdbcUrl(); String user = postgres.getUsername(); String pass = postgres.getPassword(); try (Connection conn = DriverManager.getConnection(url, user, pass); Statement stmt = conn.createStatement()) { stmt.execute("CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR(255));"); stmt.execute("INSERT INTO test VALUES (1, 'hello');"); ResultSet rs = stmt.executeQuery("SELECT name FROM test WHERE id=1;"); rs.next(); String name = rs.getString("name"); assertEquals("hello", name); } } }
Output
Test passed successfully with PostgreSQL container started and query verified.
Common Pitfalls
- Not annotating the test class with
@Testcontainerscauses containers not to start automatically. - Declaring container fields without
@Containermeans you must start/stop containers manually. - Using old Docker image tags may cause compatibility issues; always use supported versions.
- Forgetting to add the Testcontainers dependency in your build file will cause compilation errors.
java
import org.junit.jupiter.api.Test; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.containers.PostgreSQLContainer; /* Wrong way: Missing @Testcontainers annotation */ public class WrongTest { @Container public PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.2"); @Test void test() { // Container won't start automatically } } /* Right way: Add @Testcontainers annotation */ @Testcontainers public class RightTest { @Container public PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.2"); @Test void test() { // Container starts automatically } }
Quick Reference
| Feature | Description |
|---|---|
| @Testcontainers | Enables automatic container lifecycle management in JUnit tests |
| @Container | Marks a container field to be started and stopped automatically |
| Container classes | Predefined classes for common services like PostgreSQL, MySQL, Kafka |
| getJdbcUrl(), getUsername(), getPassword() | Methods to get connection info from containers |
| withDatabaseName(), withUsername(), withPassword() | Configure container settings before start |
Key Takeaways
Annotate your test class with @Testcontainers to enable automatic container management.
Use @Container on container fields to start and stop Docker containers during tests.
Configure containers with methods like withDatabaseName() before tests run.
Always use supported Docker image versions to avoid compatibility issues.
Add Testcontainers dependencies to your build file to compile and run tests.