0
0
JunitHow-ToBeginner ยท 4 min read

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 PostgreSQLContainer represent 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 @Testcontainers causes containers not to start automatically.
  • Declaring container fields without @Container means 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

FeatureDescription
@TestcontainersEnables automatic container lifecycle management in JUnit tests
@ContainerMarks a container field to be started and stopped automatically
Container classesPredefined 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.