PHpullh
학습 라이브러리/Java/TestContainers & 통합 테스트

JAVA · 테스트

TestContainers & 통합 테스트

Docker 컨테이너로 실제 DB/서비스를 띄워 통합 테스트를 작성합니다.

테스트고급TestContainersIntegration TestPostgreSQL@ContainerDocker

핵심 설명

Docker 컨테이너로 실제 DB/서비스를 띄워 통합 테스트를 작성합니다.

Java code

import org.junit.jupiter.api.*;
import org.testcontainers.containers.*;
import org.testcontainers.junit.jupiter.*;
import org.testcontainers.utility.DockerImageName;
import java.sql.*;

// TestContainers — 실제 PostgreSQL 컨테이너
@Testcontainers
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class UserRepositoryIT {

    @Container
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>(DockerImageName.parse("postgres:15"))
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    Connection connection;

    @BeforeAll
    void setup() throws SQLException {
        connection = DriverManager.getConnection(
            postgres.getJdbcUrl(),
            postgres.getUsername(),
            postgres.getPassword());

        // 스키마 생성
        connection.createStatement().execute("""
            CREATE TABLE users (
                id SERIAL PRIMARY KEY,
                name VARCHAR(100) NOT NULL,
                email VARCHAR(255) UNIQUE
            )
            """);
    }

    @Test
    @DisplayName("사용자 저장 & 조회")
    void saveAndFind() throws SQLException {
        // Given
        var insert = connection.prepareStatement(
            "INSERT INTO users (name, email) VALUES (?, ?)");
        insert.setString(1, "Alice");
        insert.setString(2, "alice@test.com");
        insert.executeUpdate();

        // When
        var select = connection.prepareStatement(
            "SELECT * FROM users WHERE email = ?");
        select.setString(1, "alice@test.com");
        var rs = select.executeQuery();

        // Then
        assertTrue(rs.next());
        assertEquals("Alice", rs.getString("name"));
    }

    @AfterAll
    void teardown() throws SQLException {
        if (connection != null) connection.close();
    }
}

// Redis 컨테이너 예시:
// @Container
// static GenericContainer<?> redis =
//     new GenericContainer<>("redis:7")
//         .withExposedPorts(6379);

학습 팁

TestContainers는 @Container가 붙은 컨테이너를 테스트 시작 전 자동으로 시작하고 종료 시 정리합니다. Docker 데몬이 실행 중이어야 합니다.

주의할 점

@Container를 static으로 선언하면 클래스 내 모든 테스트가 같은 컨테이너를 공유합니다. 각 테스트가 독립적인 컨테이너가 필요하면 인스턴스 필드로 선언하세요.

자주 묻는 질문

TestContainers & 통합 테스트란 무엇인가요?

Docker 컨테이너로 실제 DB/서비스를 띄워 통합 테스트를 작성합니다.

TestContainers & 통합 테스트 학습 시 주의할 점은 무엇인가요?

@Container 를 static으로 선언하면 클래스 내 모든 테스트가 같은 컨테이너를 공유합니다. 각 테스트가 독립적인 컨테이너가 필요하면 인스턴스 필드로 선언하세요.