@DataJpaTest (인메모리 DB 사용):
@DataJpaTest는 간단한 CRUD를 검증하는 데는 유용하지만, 운영 환경과의 완벽한 동일성을 보장하지는 못합니다.@SpringBootTest (실제 DB 연결):
@Transactional로 롤백할 수 있지만 한계가 있음)Testcontainers는 JUnit 테스트 코드 내에서 Docker 컨테이너를 프로그래매틱하게 생성하고 관리할 수 있게 해주는 Java 라이브러리입니다.
핵심 아이디어: 테스트가 실행될 때마다, 필요한 소프트웨어(DB, Redis, Kafka 등)가 설치된 Docker 컨테이너를 즉석에서 띄우고, 테스트가 끝나면 컨테이너를 자동으로 파기합니다.
@SpringBootTest와 Testcontainers를 이용한 통합 테스트@SpringBootTest의 "실제 환경과 유사함"이라는 장점과, Testcontainers의 "환경 독립성 및 격리"라는 장점을 결합하여, 가장 이상적인 데이터베이스 통합 테스트 환경을 구축할 수 있습니다.의존성 추가: build.gradle에 testcontainers와 사용할 데이터베이스(e.g., mysql)에 대한 의존성을 추가합니다.
테스트 컨테이너 설정:
@SpringBootTest가 붙은 테스트 클래스에 @Testcontainers 어노테이션을 추가하여 Testcontainers 기능을 활성화합니다.@Container 어노테이션을 사용하여, 테스트 중에 실행할 Docker 컨테이너를 정의합니다. MySQLContainer와 같은 공식 지원 모듈을 사용하면 설정이 매우 간편합니다.@DynamicPropertySource를 사용하여, 동적으로 생성된 컨테이너의 접속 정보(JDBC URL, username, password)를 Spring Boot의 application.yml 설정값에 런타임에 주입합니다.@SpringBootTest
@Testcontainers // Testcontainers 활성화
class MyIntegrationTest {
// static으로 선언하여 클래스 내 모든 테스트에서 컨테이너를 공유
@Container
static MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql:8.0");
// 동적으로 생성된 컨테이너의 접속 정보를 Spring 설정에 주입
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mySQLContainer::getJdbcUrl);
registry.add("spring.datasource.username", mySQLContainer::getUsername);
registry.add("spring.datasource.password", mySQLContainer::getPassword);
}
@Autowired
private MyService myService;
@Test
void integrationTest() {
// 이 테스트는 실제 MySQL 8.0 Docker 컨테이너 위에서 실행됨
// ...
}
}
테스트 실행:
@DynamicPropertySource가 컨테이너의 동적 포트와 자격 증명을 Spring의 DataSource 설정에 덮어씁니다.@SpringBootTest는 이 설정으로 Spring 컨테이너를 구동하고, 실제 DB 커넥션을 맺습니다.@DataJpaTest는 빠르지만 운영 환경과의 차이라는 한계가 있고, 실제 DB를 사용하는 @SpringBootTest는 환경 의존성과 격리에 어려움이 있습니다.@SpringBootTest와 Testcontainers를 함께 사용하면, @DynamicPropertySource를 통해 동적으로 생성된 DB 컨테이너의 접속 정보를 Spring에 주입하여, 신뢰도 높고 재현 가능한 데이터베이스 통합 테스트를 작성할 수 있습니다.