[OpenSource] Testcontainers로 테스트 환경 구축하기

0. 들어가며

테스트 환경을 구축할 수 있는 오픈소스 Testcontainers에 대하여 알아보겠습니다.

 

1. Testcontainers란?

  • Java, go 등 여러 언어에서 사용할 수 있는 Test 환경 구성 오픈소스입니다.
  • 프로젝트 유닛, 통합 테스트를 진행할때 DBMS, Kafka, Nginx등의 외부 서비스와는 격리하여 테스트를 작성하는 경우가 많습니다.
  • 테스트를 하더라도, test 수행으로 인해 환경이 오염되고 깨지는 문제가 발생할 수 있죠.
  • 예를 들어 운영 환경에서, Postgre SQL을 쓰지만 test 환경에서 인메모리 H2 Database를 사용할 수 있는데, 이는 정확한 환경 일치라고 할 수 없습니다. 개발자 입장에서 PostgreSQL의 새롭고 좋은 기능을 발견해도, H2 Database에 구현되어 있지않으면 쉽게 도입할 수 없는 이유가 될 수 있다.
  • 이러한 문제점을 해결해주는것이 Testcontainers입니다. Ddocker Container기반으로 Test 수행마다 실제와 같은 환경을 구현해줍니다.

https://testcontainers.com

 

Testcontainers

Testcontainers is an opensource library for providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

testcontainers.com

 

2. MySQL 환경 설정

다양한 인프라 구축을 수행해주는데요, 그 중에서 개인적으로 많이 사용하는 DBMS인 MySQL을 JUnit 기반으로 구축했을때, 간단히 테스트하는 코드를 작성해봤습니다.

 

@SpringBootTest
@Testcontainers
class MemberServiceTest {

    @Container
    static MySQLContainer<?> mysql = new MySQLContainer<>("mysql")
			    .withUrlParam("serverTimezone", "Asia/Seoul");

    @Autowired
    MemberService memberService;

    //Docker기반으로 생성한 MySQL 컨테이너를 동적으로 연결해주는 역할을함.
    @DynamicPropertySource
    static void mysqlProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", mysql::getJdbcUrl);
        registry.add("spring.datasource.username", mysql::getUsername);
        registry.add("spring.datasource.password", mysql::getPassword);
    }

    @DisplayName("이름과 핸드폰정보로 회원가입 할 수 있다.")
    @Test
    void createMemberTest(){
        CreateMemberReq req = new CreateMemberReq();
        req.setName("세종대왕");
        req.setPhone("010-0000-0000");

        Integer memberId = memberService.createMember(req);
        Member createdMember = memberService.findMember(memberId);

        assertThat(createdMember).extracting("id","name","phone")
                .containsExactly(
                        memberId,
                        req.getName(),
                        req.getPhone()
                );
    }
}

 

  1. 먼저 @Testcontainers 어노테이션으로 해당 테스트에서 컨테이너를 사용할것을 명시합니다.
  2. @Container를 통해 컨테이너 객체를 지정합니다.
  3. Docker Container이름을 파라미터로 넘기는데 버전을 안쓰면 latest버전으로 빌드합니다.
  4. withUrlParam()으로 Url에 파라미터를 넘길 수도 있습니다.
  5. @DynamicPropertySource가 중요한데, Test시 생성되는 MySQL 컨테이너를 동적으로 연결해주는 역할을합니다.\

이 외에도 정말 많은 모듈과 언어를 제공하고있어, 공식 페이지에서 필요한 모듈을 알아보면 좋을거같습니다!