Testcontainers는 도커를 이용하여 테스트 환경을 분리해주는 라이브러리이다.
테스트 수행 시 DB 등의 외부 환경은 운영 환경과 다르게 구축해야 할 필요가 있는데, 보통은 로컬 PC 에 테스트 전용 DB 를 만들어서 사용해왔다.
RDB 까지는 이렇게 독립적인 환경에서 테스트를 한다고 하더라도, Redis 나 Elasticsearch 와 같은 데이터저장소들은 개발에 참여하는 개개인이 모두 로컬 환경을 설정하는 것은 쉬운 일이 아니다.
이럴 때 도커는 매우 적절한 선택이 될 수 있고, Testcontainers 는 그 도커의 설정도 필요없게끔 Convention 이 설정되어 있기 때문에 사용하기에 매우 편리하다.
설치
junit 4 junit 5 ← 버전 별로 설치 방법이 다르다.
// kotlin 코드
testImplementation("org.testcontainers:testcontainers:${Versions.testcontainersVersion}")
testImplementation("org.testcontainers:junit-jupiter:${Versions.testcontainersVersion}")
공식 문서에 보면 다양한 의존성들을 설치하는데, 본인이 필요한 것을 골라서 설치하면 된다.
컨테이너 재사용 설정 방법
제대로 설치하고 실행해보면, 테스트 수행 시에 도커 컨테이너가 실행되는 것을 볼 수 있다.
그런데 테스트 수행 시 마다 새로운 컨테이너를 실행하니, 시간이 매우 오래 걸린다.
이를 피하기 위해 컨테이너를 재사용하고자 한다.
Testcontainers Github 재사용 기능 PR
Local 환경에 재사용 설정 추가
$ vim ~/.testcontainers.properties
testcontainers.reuse.enable=true // 추가
컨테이너 Singleton 설정
문서에 보면 Shared container, Singleton Container 이렇게 2가지 방식이 소개되어 있는데, 여러 단위 테스트에 적용하기에는 Singleton 방식이 더 적합해 보인다.
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
abstract class AbstractContainerBaseTest {
companion object {
@JvmStatic
protected val MY_SQL_CONTAINER: MySQLContainer<*> = MySQLContainerProvider()
.newInstance()
.withReuse(true) as MySQLContainer<*>
@JvmStatic
protected val ELASTICSEARCH_CONTAINER: ElasticsearchContainer = ElasticsearchContainer(
"docker.elastic.co/elasticsearch/elasticsearch:7.12.1"
).withReuse(true)
}
...
재사용 메소드 이용
.withReuse(true)
함수를 이용하여 해당 컨테이너를 재사용 하도록 지정해준다.
실행
테스트를 실행하기 전, 도커를 실행해야 한다.
테스트를 수행한다.
$ ./gradlew test
컨테이너들이 자동으로 생성되었다.
본 환경에서는 재사용 설정을 해두었기 때문에 테스트가 종료된 이후에도 컨테이너가 실행되고 있다.
도커 컨테이너 stat 을 살펴보자
이렇게 자원을 계속 사용하고 있다.
따라서 테스트를 수행하고 난 이후에 더이상 사용할 필요가 없다면 해당 컨테이너를 종료시켜야 한다. (이 부분이 좀 찝찝한데, 더 좋은 방법이 있는지 좀 더 확인이 필요하다.)