0
0
JUnittesting~5 mins

Test containers for database testing in JUnit

Choose your learning style9 modes available
Introduction

Test containers let you run a real database in a temporary environment during tests. This helps check your code works with a real database without needing a permanent setup.

You want to test database queries without changing your main database.
You need a clean database for each test to avoid data conflicts.
You want to test your code on different database versions easily.
You want to run tests on any machine without installing a database.
You want to catch database-related bugs early during development.
Syntax
JUnit
public class MyDatabaseTest {
    @Container
    public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.3")
        .withDatabaseName("testdb")
        .withUsername("user")
        .withPassword("pass");

    @BeforeAll
    public static void setup() {
        // Setup code to connect to the container database
    }

    @Test
    public void testQuery() {
        // Your test code here
    }
}

Use the @Container annotation to manage the lifecycle of the test container.

Testcontainers automatically starts and stops the database container for your tests.

Examples
This example starts a PostgreSQL container and checks if it is running.
JUnit
public class SimplePostgresTest {
    @Container
    public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.3");

    @Test
    public void testConnection() {
        assertTrue(postgres.isRunning());
    }
}
This example shows how to customize the database name and credentials.
JUnit
public class CustomDbTest {
    @Container
    public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.3")
        .withDatabaseName("mydb")
        .withUsername("admin")
        .withPassword("secret");

    @Test
    public void testDbName() {
        assertEquals("mydb", postgres.getDatabaseName());
    }
}
Sample Program

This test starts a PostgreSQL container, creates a table, inserts data, and checks the number of rows.

JUnit
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeAll;
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.*;

@Testcontainers
public class DatabaseTest {

    @Container
    public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.3")
        .withDatabaseName("testdb")
        .withUsername("user")
        .withPassword("pass");

    private static Connection connection;

    @BeforeAll
    public static void setUp() throws Exception {
        String url = postgres.getJdbcUrl();
        String username = postgres.getUsername();
        String password = postgres.getPassword();
        connection = DriverManager.getConnection(url, username, password);

        try (Statement stmt = connection.createStatement()) {
            stmt.execute("CREATE TABLE IF NOT EXISTS items (id SERIAL PRIMARY KEY, name VARCHAR(255));");
            stmt.execute("INSERT INTO items (name) VALUES ('apple'), ('banana');");
        }
    }

    @Test
    public void testItemCount() throws Exception {
        try (Statement stmt = connection.createStatement()) {
            ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM items;");
            assertTrue(rs.next());
            int count = rs.getInt(1);
            assertEquals(2, count);
        }
    }
}
OutputSuccess
Important Notes

Testcontainers require Docker to be installed and running on your machine.

Each test container runs isolated, so tests do not affect each other.

Use @Testcontainers annotation on the test class to enable container support.

Summary

Test containers let you test with real databases easily and safely.

They start and stop databases automatically during tests.

This helps catch database issues early without manual setup.