Testing · 2025-07-10 · 1분 읽기
Testcontainers로 실제 DB 쓰는 통합 테스트 작성하기
목차
- ›1. H2 테스트의 문제점
- ›2. 의존성 추가
- ›3. 기본 설정
- ›4. 공유 컨테이너로 테스트 속도 개선
- ›5. @Sql로 테스트 데이터 관리
- ›6. Redis, Kafka도 동일하게
1. H2 테스트의 문제점
- MySQL 전용 함수 (
DATE_FORMAT,REGEXP_LIKE등) 사용 불가 - JSON 타입, 전문검색 등 MySQL 특화 기능 테스트 불가
- 실제 인덱스 동작 확인 불가
- 마이그레이션 스크립트(Flyway/Liquibase) 검증 불가
2. 의존성 추가
testImplementation 'org.testcontainers:junit-jupiter:1.19.3'
testImplementation 'org.testcontainers:mysql:1.19.3'3. 기본 설정
@SpringBootTest
@Testcontainers
class UserRepositoryTest {
@Container
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}
@Autowired
UserRepository userRepository;
@Test
void 사용자를_이메일로_조회한다() {
userRepository.save(new User("홍길동", "hong@example.com"));
Optional<User> found = userRepository.findByEmail("hong@example.com");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("홍길동");
}
}4. 공유 컨테이너로 테스트 속도 개선
매 테스트 클래스마다 컨테이너를 새로 띄우면 느리다. 하나를 공유하면 전체 테스트 시간이 크게 줄어든다.
// AbstractIntegrationTest.java
@SpringBootTest
@Testcontainers
public abstract class AbstractIntegrationTest {
static final MySQLContainer<?> mysql;
static {
mysql = new MySQLContainer<>("mysql:8.0")
.withDatabaseName("testdb")
.withReuse(true); // 컨테이너 재사용
mysql.start();
}
@DynamicPropertySource
static void properties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}
}
// 실제 테스트
class OrderServiceTest extends AbstractIntegrationTest {
@Test
void 주문_생성_테스트() { ... }
}5. @Sql로 테스트 데이터 관리
@Test
@Sql("/sql/insert-users.sql")
@Sql(scripts = "/sql/cleanup.sql", executionPhase = AFTER_TEST_METHOD)
void 사용자_목록_조회() {
List<User> users = userRepository.findAll();
assertThat(users).hasSize(3);
}-- /sql/insert-users.sql
INSERT INTO users (name, email) VALUES ('홍길동', 'hong@test.com');
INSERT INTO users (name, email) VALUES ('김철수', 'kim@test.com');
INSERT INTO users (name, email) VALUES ('이영희', 'lee@test.com');6. Redis, Kafka도 동일하게
@Container
static GenericContainer<?> redis = new GenericContainer<>("redis:7")
.withExposedPorts(6379);
@Container
static KafkaContainer kafka = new KafkaContainer(
DockerImageName.parse("confluentinc/cp-kafka:7.4.0")
);'Testing ' 카테고리의 다른 글
- 이 카테고리에 다른 글이 없습니다.