로컬에 Redis를 띄워서 테스트 코드를 검증할 수도 있지만, 테스트 코드는 동일한 환경에서 실행되어야 한다고 생각하기 때문에 다른 방법을 찾아봤다.
속도를 감안하더라도 격리된 환경에서 테스트를 할 수 있기 때문에 TestContainer
를 선택했다.
testImplementation "org.testcontainers:testcontainers:1.19.0"
testImplementation "org.testcontainers:junit-jupiter:1.19.0"
main 경로에 생성한다.
@EnableCaching
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String host;
@Value("${spring.data.redis.port}")
private int port;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
@Bean
public RedisTemplate<String, Long> redisTemplate() { // 인자에 따라 설정 다르게 하기
RedisTemplate<String, Long> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(
new GenericToStringSerializer<>(Long.class)); // Long 값을 다루므로 설정 변경
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}
test 경로에 생성한다.
@Testcontainers
public class RedisTestContainerConfig {
private static final String REDIS_IMAGE = "redis:7.0.8-alpine";
private static final int REDIS_PORT = 6379;
private static final GenericContainer REDIS_CONTAINER;
static {
REDIS_CONTAINER = new GenericContainer(REDIS_IMAGE)
.withExposedPorts(REDIS_PORT)
.withReuse(true);
REDIS_CONTAINER.start();
}
@DynamicPropertySource
private static void registerRedisProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.redis.host", REDIS_CONTAINER::getHost);
registry.add("spring.data.redis.port", () -> REDIS_CONTAINER.getMappedPort(REDIS_PORT)
.toString());
}
}
spring.data.redis.host 를 주의하자. 블로그 보고 따라했다가 경로가 달라서 고생했다.
@Nested
@DisplayName("상품의 총 리뷰 수를 추가하는 서비스 실행 시")
class PlusOneToTotalNumberOfReviewsByItemId {
@Test
@DisplayName("Redis에 값이 없으면 DB에서 가져오고, 값이 있으면 Redis에 총 리뷰 수를 +1한다.")
void shouldPlusOneToTotalNumberOfReviewsByItemId() {
// given
mainCategoryRepository.save(givenMainCategory);
subCategoryRepository.save(givenSubCategory);
itemRepository.save(givenItem);
userRepository.save(givenUser);
reviewRepository.save(givenReview);
String cacheKey = "reviewCount:Item:" + givenItem.getItemId();
// when
redisCacheService.plusOneToTotalNumberOfReviewsByItemId(givenItem.getItemId(),
cacheKey);
Long dbCount = redisCacheService.getTotalNumberOfReviewsByItemId(
givenItem.getItemId(), cacheKey);
Long cachedCount = redisCacheService.getTotalNumberOfReviewsByItemId(
givenItem.getItemId(), cacheKey);
// then
assertEquals(dbCount, cachedCount);
}
}
처음에는 DB에서 데이터를 가져와 쿼리문을 확인할 수 있었고, 두번째는 Redis에서 이용하기 때문에 쿼리문 없이 데이터를 가져왔다.
https://github.com/prgrms-be-devcourse/BE-04-NaBMart
https://devoong2.tistory.com/entry/Springboot-Redis-테스트-환경-구축하기-Embedded-Redis-TestContainer