본문 바로가기
BackEnd/Project

[PharmNav] Ch08. Redis 테스트 코드 작성

by 개발 Blog 2024. 9. 5.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

이번 시간에는 Redis를 활용해 약국 데이터를 조회하고, 이를 검증하는 테스트 코드를 작성해 보며 Redis의 활용성을 점검해 본다. 또한, Redis 장애 시 DB를 활용하는 전략도 함께 검증해 본다.

 

1. 약국 검색 서비스 테스트

첫 번째로 검증할 부분은 PharmacySearchService에서 Redis 장애가 발생했을 때 DB를 이용해 약국 데이터를 조회하는지 확인하는 테스트다.

package com.example.phamnav.pharmacy.service

import com.example.phamnav.pharmacy.cache.PharmacyRedisTemplateService
import com.example.phamnav.pharmacy.entity.Pharmacy
import com.google.common.collect.Lists
import spock.lang.Specification

class PharmacySearchServiceTest extends Specification {
    private PharmacySearchService pharmacySearchService

    private PharmacyRepositoryService pharmacyRepositoryService = Mock()
    private PharmacyRedisTemplateService pharmacyRedisTemplateService = Mock()

    private List<Pharmacy> pharmacyList

    def setup() {
        pharmacySearchService = new PharmacySearchService(pharmacyRepositoryService, pharmacyRedisTemplateService)

        pharmacyList = Lists.newArrayList(
                Pharmacy.builder()
                        .id(1L)
                        .pharmacyName("호수온누리약국")
                        .latitude(37.60894036)
                        .longitude(127.029052)
                        .build(),
                Pharmacy.builder()
                        .id(2L)
                        .pharmacyName("돌곶이온누리약국")
                        .latitude(37.61040424)
                        .longitude(127.0569046)
                        .build()
        )
    }

    def "레디스 장애시 DB를 이용 하여 약국 데이터 조회"() {

        when:
        pharmacyRedisTemplateService.findAll() >> []
        pharmacyRepositoryService.findAll() >> pharmacyList

        def result = pharmacySearchService.searchPharmacyDtoList()

        then:
        result.size() == 2
    }
}

 

  • Redis에서 약국 데이터를 찾지 못하는 상황을 가정하고, DB에서 데이터를 조회하여 정상적으로 결과를 반환하는지 확인한다.
  • pharmacyRedisTemplateService.findAll() 호출 시 빈 배열을 반환하고, pharmacyRepositoryService.findAll()이 DB에서 약국 데이터를 조회한다.
  • 테스트 결과가 예상한 대로 2개의 약국 데이터가 조회되면 테스트를 통과한다.

 

 

2. PharmacyRedisTemplateServiceTest 통합 테스트

이 테스트는 실제 Redis 서버를 이용해 통합 테스트를 진행한다. Redis에 데이터를 저장하고 조회하는 과정을 검증한다.

package com.example.phamnav.pharmacy.cache

import com.example.phamnav.AbstractIntegrationContainerBaseTest
import com.example.phamnav.pharmacy.dto.PharmacyDto
import org.springframework.beans.factory.annotation.Autowired

class PharmacyRedisTemplateServiceTest extends AbstractIntegrationContainerBaseTest {

    @Autowired
    private PharmacyRedisTemplateService pharmacyRedisTemplateService

    def setup() {
        pharmacyRedisTemplateService.findAll()
        .forEach(dto -> {
            pharmacyRedisTemplateService.delete(dto.getId())
        })
    }

    def "save success"() {
        given:
        String pharmacyName = "name"
        String pharmacyAddress = "address"
        PharmacyDto dto =
                PharmacyDto.builder()
                        .id(1L)
                        .pharmacyName(pharmacyName)
                        .pharmacyAddress(pharmacyAddress)
                        .build()

        when:
        pharmacyRedisTemplateService.save(dto)
        List<PharmacyDto> result = pharmacyRedisTemplateService.findAll()

        then:
        result.size() == 1
        result.get(0).id == 1L
        result.get(0).pharmacyName == pharmacyName
        result.get(0).pharmacyAddress == pharmacyAddress
    }

    def "success fail"() {
        given:
        PharmacyDto dto =
                PharmacyDto.builder()
                        .build()

        when:
        pharmacyRedisTemplateService.save(dto)
        List<PharmacyDto> result = pharmacyRedisTemplateService.findAll()

        then:
        result.size() == 0
    }

    def "delete"() {
        given:
        String pharmacyName = "name"
        String pharmacyAddress = "address"
        PharmacyDto dto =
                PharmacyDto.builder()
                        .id(1L)
                        .pharmacyName(pharmacyName)
                        .pharmacyAddress(pharmacyAddress)
                        .build()

        when:
        pharmacyRedisTemplateService.save(dto)
        pharmacyRedisTemplateService.delete(dto.getId())
        def result = pharmacyRedisTemplateService.findAll()

        then:
        result.size() == 0
    }
}

save 

  • Redis에 약국 데이터를 저장한 후, 해당 데이터가 정상적으로 저장되었는지 조회하여 검증한다.
  • result.size()를 통해 데이터가 1개 저장되었음을 확인하고, 저장된 약국의 id 값을 검증한다.

fail

  • 비어 있는 데이터를 저장하려고 할 때 Redis에 저장되지 않아야 한다.
  • result.size()가 0인지를 확인해 데이터가 저장되지 않았음을 검증한다.

delete

  • Redis에 데이터를 저장한 후, 해당 데이터를 삭제하는 과정을 테스트한다.
  • 데이터를 삭제한 후 조회했을 때, 데이터가 없음을 확인하여 테스트를 통과한다.

 

3. 실제 서비스 테스트

모든 테스트가 통과한 후, 실제로 서비스를 실행해 DB에서 데이터를 가져와 Redis에 저장하고 있는지 확인한다.

 

웹 로그 확인

/redis/save 경로로 GET 요청을 보내면, 정상적으로 "success" 응답이 반환되는 것을 확인할 수 있다. 이 과정에서 약국 데이터가 DB에서 Redis로 성공적으로 저장된다.

웹페이지에서 정상적으로 로그가 찍히는 것을 볼 수 있다. 

 

데이터 저장 로그 확인
Redis에 약국 데이터를 저장하면, 23888개의 약국 데이터가 정상적으로 저장되었음을 로그에서 확인할 수 있다.

 

Redis 데이터 확인
Redis 컨테이너에 접속하여 hgetall key 명령어로 모든 데이터를 조회한다. 해시 자료구조로 약국 데이터가 정상적으로 저장된 것을 확인할 수 있다.

 

주소 검색 기능 테스트
웹페이지에서 주소를 입력한 후 검색하면 Redis를 통해 약국 데이터를 불러와 결과를 반환한다. 

//redis
List<PharmacyDto> pharmacyDtoList = pharmacyRedisTemplateService.findAll();
if(!pharmacyDtoList.isEmpty()){
    log.info("redis findAll success!");
    return pharmacyDtoList;
}

 

서버 로그에서도 redis findAll success! 메시지가 출력되는 것을 확인할 수 있다.

 

이번 시간에는 Redis와 DB를 연동한 약국 검색 서비스의 테스트를 진행하고, Redis에 데이터를 저장하고 조회하는 과정을 확인했다. 모든 테스트를 통과하였으며, 실제 서비스에서 Redis를 활용한 데이터 조회가 정상적으로 이루어졌다. 다음 시간에는 AWS 클라우드 서비스에 프로젝트를 배포하여 Redis를 포함한 전체 시스템을 검증해 볼 예정이다.