Testcontainers로 테스트 환경 구성하기 1 (w. Spring, JPA)

🔥Log·2024년 7월 23일

테스트

목록 보기
4/5

💡 글에서 사용되는 코드: 깃헙

☕ 개요


이번 글에서는 Testcontainers를 활용해서 멱등성이 보장되는 통합 테스트 환경을 구축해보도록 하겠다. Testcontainers가 무엇인지, 사용하면 어떤 장점이 있는지와 같은 설명은 좋은 글들이 이미 많이 있으므로, 나는 JPA와 Testcontainers와 연동해서 환경을 구축해보는 실습 위주의 글을 작성해보겠다.

그럼 바~로 ㄱㄱ



🐘 build.gradle


dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'

    runtimeOnly 'com.mysql:mysql-connector-j'
    compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'

    testImplementation 'org.springframework.boot:spring-boot-starter-test' 
    testImplementation 'org.springframework.boot:spring-boot-testcontainers'
    testImplementation 'org.testcontainers:junit-jupiter'
    testImplementation 'org.testcontainers:mysql:1.20.0'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    testCompileOnly 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
}

데이터베이스는 MySQL을 사용한다는 가정하에 필요한 의존성 목록이다.

testImplementation 'org.springframework.boot:spring-boot-testcontainers'
testImplementation 'org.testcontainers:junit-jupiter'

이 두 라이브러리는 Boot 서버에서 Testcontainers를 사용하기 위한 가장 기본적인 라이브러리이다.

testImplementation 'org.testcontainers:mysql:1.20.0'

이 라이브러리는 드라이버 역할을 하는 녀셕이고, DB의 종류 또는 컨테이너화 하려고하는 툴마다 라이브러리가 존재하므로, 각자에 맞는 라이브러리를 사용하면 된다.



🧐 설정하기


1) 잠깐

@TestConfiguration(proxyBeanMethods = false)
public class TestcontainersConfiguration {

    @Container
    public static MySQLContainer MYSQL_CONTAINER = new MySQLContainer("mysql:8.4.1")
            .withDatabaseName("tc_test")
            .withUsername("root")
            .withPassword("1234");

}

공식문서나 많은 블로그에서 위와 같은 방식으로 테스트컨테이너 설정을 안내하고 있는데, JPA처럼 Datasource가 만들어지는 상황이라면, 직접 테스트 컨테이너 설정을 해주지 않아도 된다.

2) Datasource 설정하기

spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:mysql:8.4.1://localhost:3306/tc_test
spring.datasource.username=root
spring.datasource.password=1234

test/resources 하위에 만들어준 application.properties파일이다. 여기서 주목할 부분은 당연히도 url과 드라이버 설정이다.

url의 시작부분에 tc는 Testcontainers를 나타내는 Dialect 또는 약속어이고, mysql:8.4.1은 도커 이미지를 나타낸다.

참고로 localhost:3306은 생략이 가능해서 아래와 같이 표현해도 무방하다.

spring.datasource.url=jdbc:tc:mysql:8.4.1:///tc_test

Testcontainers의 MySQL 모듈을 패키지로 설치하고 Datasource 정보에 Testcontainer에 대한 키워드들을 명시해주면, Testcontainers가 알아서 MySQL 컨테이서를 만들어준다.



💻 테스트 하기


1) 테스트 코드 작성

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@SpringBootTest
@ExtendWith(SpringExtension.class)
class PostRepositoryTest {

    @Autowired
    private PostRepository postRepository;

    @Test
    void 생성과_조회() throws Exception {
        // given
        Post post = postRepository.save(Post.create("제목", "내용"));
        Long savedId = post.getId();

        // when
        Optional<Post> optionalPost = postRepository.findById(savedId);

        // then
        Post foundPost = optionalPost.orElseThrow(() -> new IllegalArgumentException("게시글을 찾을 수 없습니다."));
        assertThat(foundPost.getTitle()).isEqualTo("제목");
        assertThat(foundPost.getContent()).isEqualTo("내용");
    }

}

엔티티나 레포지토리 관련 코드까지 설명하면 너무 길어지니 생략하고 바로 테스트 코드부터 소개하도록 하겠다. 이 테스트 코드도 사실 별 것은 없고, 데이터를 생성하고 잘 조회되는지 확인하는 코드이다.

@Testcontainers

다만, 테스트 클래스 상단에 붙어 있는 이 어노테이션이 중요하다. 이 어노테이션을 붙이면, @BeforeAll 시점에 컨테이너가 실행되고, @AfterAll타이밍에 컨테이너가 종료되게 된다.

즉, 하나의 테스트 클래스를 기준으로 컨테이너를 띄웠다가 내리는 것이다. (컨테이너를 띄우고 내리는 기준은 변경 가능하다.)

2) 동작 확인

테스트 코드를 실행하면 이렇게 성공한다. 즉, 도커 컨테이너로 띄워진 DB에 붙어서 테스트 코드가 잘 실행됐다는 것을 알 수 있는 것이다.

그리고, 테스트가 실행되는 중에는 이렇게 컨테이너가 실행되고 테스트가 완료되면 컨테이너들이 종료되는 것 또한 확인할 수 있다.



🙏 참고


2개의 댓글

comment-user-thumbnail
2025년 5월 15일

yml 에 설정하니 @TestContainer 를 안붙여도 도커가 떴다가 테스트 종료시 내려가는것 같아요

1개의 답글