[Spring] TestContainers로 Redis 테스트하기

반응형

테스트 코드로 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)

 

개발 운영 환경과 비슷한 로컬 환경 구축하기 (feat. TestContainer)

현재 진행하고 있는 "오디"프로젝트는 다음과 같이 3가지 환경으로 구성되어 있다.각 환경에 대해 간단히 설명하자면Local 환경은 각자 기능을 개발 해 PR을 보내는 용도.Dev 환경은 EC2로 애플리케

hstory0208.tistory.com


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를 테스트할 방법이 마땅히 있는 것 같진 않다.