[Spring] Test Container를 통한 Repository 계층 테스트하기

윤성철·2024년 10월 24일

Back-End

목록 보기
15/22
post-thumbnail

서론

최근 테스트 코드를 작성하면서, 이전에 적용했던 인메모리 DB를 기반으로 테스트 하는 방식에 의문점을 가지게 되었다.

Repository 계층의 역할은 DB와 의존성을 맺어서 데이터를 주거니 받거니한다. 그러나, Mock이나 InmemoryDB를 통해 테스트를 독립적으로 수행한다면, 운영 환경 DB인 MariaDB와 트랜잭션 처리 방식의 다른점, 제약 조건 및 인덱스가 다름으로 인해 신뢰성이 낮은 테스트 결과를 얻을 수 있다. 이렇게 되면, 오류를 사전에 방지하기 위해서인 테스트의 목적을 충족시키지 못하는거 아닐까라는 생각이 들었다. 덧붙여서, 배포환경과 로컬환경의 DB 내부 데이터가 다르면, 결국 테스트 커버리지의 범위가 상이할 수 밖에 없다라고 생각이 들었다.

그래서 실무에서는 어떻게 테스트 환경을 운영하는지 개발자 단톡방에서 물어봤다.

본론

테스트를 수행하는데 있어서, 가장 중요한 점은 멱등성, 편의성이라고 생각했다.

누가, 어떤 환경에서라도 테스트를 수행했을 때 동일한 결과가 나와야한다. 또한, 최대한 운영 환경과 유사한 조건으로 테스트 환경을 구축해야 한다. 그리고, 현재는 백엔드 서버를 혼자 개발하고 있지만, 팀원들과 협업하는 과정에서 테스트를 위해 로컬에 MariaDB를 설치해야한다.

위 3가지 이유로, 기존의 InMemeoryDB에서 벗어나, Test Container를 도입하기로 결정했다.

Test Container의 특징

  • 테스트 컨테이너는 Junit을 지원하는 Java 라이브러리이다.
  • 도커 컨테이너 기반의 일회용 인스턴스를 제공한다.
  • 각종 DBMS의 이미지를 활용할 수 있다.

Test Container 적용하기

Gradle 의존성 추가

application-test.properties 파일 작성

spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:mariadb:10.11://test
spring.datasource.username={}
spring.datasource.password={}

port 기입이 생략되었는데, 그 이유는 컨테이너를 생성하고 구동할 때, 미사용중인 포트를 JVM에서 알아서 설정해준다.

Container 관련 config 작성

@DynamicPropertySource : 동적으로 프로퍼티를 설정할 때 사용하는 어노테이션으로,
사실 application-test.properties를 통해 명시했기 때문에, 작성하지 않아도 된다.

그리고, MariaDBContainer 객체를 생성할 때, static을 붙이면, 테스트 수행 이후 종료가 되도, 컨테이너를 다음에 재사용한다.

JPA의 GenerateValue와 같은 sequence 이슈가 있기에 참고해야한다!

테스트하려는 RepositoryTest에 사용하려는 프로퍼티 명시

테스트를 위한 더미데이터 세팅

datq.sql로 어플리케이션 구동시, Insert 쿼리문을 통해 데이터를 삽입하는 방식과 위처럼 더미데이터를 세팅하는 방식을 고민하다가, 시퀀스 이슈영속성 관련 테스트를 위해 위처럼 적용했다.

테스트 수행

테스트가 시작되면, MariaDB 컨테이너 이미지 유무를 검증하고, 없다면 image를 다운받는다. 다운받은 image를 기반으로 test container를 구동하고, 테스트가 종료되면 컨테이너도 내려간다.

동작중인 Test Container

테스트가 정상적으로 수행되었다. 운영환경과 같은 RDMBS를 사용했고, 이후에는 배포 환경의 데이터를 일부 가져와서 테스트를 수행하려고 한다.

profile
내 기억보단 내가 작성한 기록을 보자..

0개의 댓글