테스트 코드로 Redis를 테스트하고 싶은데 어떻게 테스트할 수 있을까?
꼭 로컬에서 Redis를 실행시켜놔야지만 테스트가 가능할까?
Redis도 H2처럼 Embedde로 테스트할 수 잇는 Embedded Redis 라이브러리가 있긴하다.
하지만 최근 커밋이 너무 오래된걸 봐선 관리가 되지 않고 있다.
kstyrc/embedded-redis : 6년 전
ozimov/embedded-redis : 4년 전
사용해보진 않았지만 많은 오류들이 발견되어 개선하지 않고 있다 알고 있다.
우리에겐 TestContainers로 테스트시에만 Redis 컨테이너를 테스트할 수 있는 방법이 있다.
TestContainers란?
우선 테스트 컨테이너에 대해 간단히 설명하고 넘어가보려 한다.
https://testcontainers.com/guides/introducing-testcontainers/
공식 문서에서는 위와 같이 설명을 하고 있는데 간단히 요약하자면
Test Containsers는 Docker 컨테이너로 실제 환경에서 사용하는 서비스를 실행 시켜
실제 환경과 동일한 유형의 서비스와 통신하는 테스트를 작성할 수 있도록 도와주는 테스트 라이브러리이다.
Test Containsers 기반 테스트를 실행하기 위한 유일한 요구사항은 Docker Desktop이 설치되어 실행 중이여야 한다는 것이다.
이 외에는 개발자가 직접 컨테이너를 실행하고 종료할 필요 없이
Test Containsers 라이브러리가 개발자가 설정한 데로 알아서 컨테이너 생명주기를 관리해준다.
TestContainers로 Redis 테스트 환경 구축하기
우선 아래 의존성을 추가해주자.
implementation 'org.testcontainers:testcontainers-bom:1.20.2'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:testcontainers'
그 다음 아래와 같이 레디스 테스트 컨테이너 설정 클래스를 추가해주기만하면 끝이다.
@TestConfiguration
@Testcontainers
public class RedisTestContainersConfig {
private static final int REDIS_PORT = 6379;
@Container
private static final GenericContainer<?> redisContainer = new GenericContainer<>("redis:7.4.1-alpine3.20")
.withExposedPorts(REDIS_PORT)
.waitingFor(Wait.forListeningPort())
.withStartupTimeout(Duration.ofSeconds(60));
static {
redisContainer.start();
}
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(
redisContainer.getHost(),
redisContainer.getMappedPort(REDIS_PORT)
);
}
}
@TestContainers
클래스 레벨에 선언하며 테스트 컨테이너의 확장 기능을 사용하기 위한 어노테이션이다.
@Container
필드 레벨에선언하며 컨테이너 생명 주기를 관리하기 위한 어노테이션이다.
인스턴스 필드에 사용하면 각 테스트마다 컨테이너가 실행돼 무수히 많은 컨테이너들이 존재하는 것을 볼 수 있다. (테스트 시간도 길어짐..)
Static 필드에 사용하면 하나의 컨테이너를 공유해 테스트할 수 있다.
Redis 테스트 컨테이너 설정은 MySQL에 비해 아주 간단하게 설정할 수 있었다.
참고로 MySQL은 전용 테스트 컨테이너 라이브러리가 MySQL컨테이너 클래스를 사용했지만
Redis는 전용 테스트 컨테이너 라이브러리가 없어 GenericContainer를 사용해 컨테이너를 생성했다.
(GenericContainer : 어떤 Docker 이미지든 실행 가능)
테스트 컨테이너에 좀 더 자세하게 알고 싶다면 아래 포스팅이 도움이 될 것이다.
2024.10.16 - [◼ JAVA/Spring] - 개발 운영 환경과 비슷한 로컬 환경 구축하기 (feat. TestContainer)
TestContainers로 Redis 테스트하기
위에서 만든 설정 클래스르 다음과 같이 import해 테스트를 작성하면 끝이다.
@Import(RedisTestContainersConfig.class)
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
class CustomRedisTemplateTest extends BaseRedisTest {
private static final String TEST_KEY = "test";
@Autowired
protected RedisTemplate redisTemplate;
@BeforeEach
void init() {
// 메서드 실행 전 캐시 초기화
redisTemplate.getConnectionFactory()
.getConnection()
.serverCommands()
.flushAll();
}
@DisplayName("key의 counter를 증가시킨다.")
@Test
void increment() {
Long keyCount = redisTemplate.opsForValue().increment(TEST_KEY);
assertThat(keyCount).isEqualTo(1);
}
}
실행 중인 docker 컨테이너를 보면 테스트 실행 시에만 컨테이너가 실행되고
테스트가 종료되면 컨테이너가 종료되는 것을 볼 수 있다.
하지만 단점이 있다면 컨테이너 실행 시간 때문에 조금 느리다는 건데
m3 Mac 기준으로 h2 테스트랑 크게 체감안되는 것 같다.
좀 많이 낮은 스펙 컴퓨터 기준으로는 조금 오래걸리긴하는데
현재로써는 TestContainers외에 Redis를 테스트할 방법이 마땅히 있는 것 같진 않다.
'◼ Spring' 카테고리의 다른 글
분산락을 적용해 동시성 문제 해결하기 (3) | 2024.11.20 |
---|---|
외부 API 의존성 분리 및 장애 대응 체계 구축하기 (0) | 2024.11.19 |
개발 운영 환경과 비슷한 로컬 환경 구축하기 (feat. TestContainer) (4) | 2024.10.16 |
[Spring] DB Replication으로 분리된 Read / Write 연결 적용하기 (5) | 2024.09.25 |
ArgumentCaptor를 사용해 method 인자 값 검증하기 (2) | 2024.09.24 |