-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 반려동물 식품 로컬 캐시 적용 #540
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,22 @@ | ||
package zipgo.common.cache; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public enum CacheType { | ||
|
||
BREEDS("breeds", 1), | ||
BREEDS("breeds"), | ||
PET_FOODS("petFoods") | ||
; | ||
|
||
CacheType(String name) { | ||
this.name = name; | ||
this.maxSize = 10000; | ||
this.expireTime = 3000; | ||
} | ||
|
||
private final String name; | ||
private final int maxSize; | ||
private final long expireTime; | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package zipgo.common.cache; | ||
|
||
import org.springframework.cache.interceptor.KeyGenerator; | ||
import org.springframework.util.StringUtils; | ||
|
||
import java.lang.reflect.Method; | ||
|
||
public class CustomKeyGenerator implements KeyGenerator { | ||
|
||
@Override | ||
public Object generate(Object target, Method method, Object... params) { | ||
return StringUtils.arrayToDelimitedString(params, "_"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
package zipgo.petfood.application; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.cache.CacheManager; | ||
import zipgo.brand.domain.Brand; | ||
import zipgo.brand.domain.repository.BrandRepository; | ||
import zipgo.common.cache.CacheType; | ||
import zipgo.common.service.ServiceTest; | ||
import zipgo.petfood.domain.Functionality; | ||
import zipgo.petfood.domain.PetFood; | ||
|
@@ -23,6 +26,7 @@ | |
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
import static java.util.Collections.EMPTY_LIST; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
@@ -50,7 +54,14 @@ | |
|
||
class PetFoodQueryServiceTest extends ServiceTest { | ||
|
||
private static final int size = 20; | ||
private static final int SIZE = 20; | ||
private static final String CACHE_KEY_DELIMITER = "_"; | ||
private static final FilterRequest EMPTY_FILTER_REQUEST = FilterRequest.of( | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST | ||
); | ||
|
||
@Autowired | ||
private PetFoodQueryService petFoodQueryService; | ||
|
@@ -67,6 +78,14 @@ class PetFoodQueryServiceTest extends ServiceTest { | |
@Autowired | ||
private FunctionalityRepository functionalityRepository; | ||
|
||
@Autowired | ||
private CacheManager cacheManager; | ||
Comment on lines
+81
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저라면, 이 부분은 따로 테스트를 했을 것 같아요. 그런 관점에서 mock test를 하면.. 캐시 매니저 구현에는 의존하지 않을 것 같아요 (사실 simpleGenerator 로직에 문제가 없었던 건 아니니까...! 바꿀 필요 없어짐) 그럼 reposiroty 구현체를 스터빙할 수 있고 (mockito 사용하면) 다음처럼 테스트할 수 있어요.
이런 식으로, 서비스 행위 테스트가 되겠죵.. 단점은 .. 시간이란 비용과.. 목테스트를 최소화하는 우리 프로젝트의 별종케이스가 되는 것.. 그리고 캐시 클래스 자체의 기능은 테스트 하지 않는다는거? -> 근데 이건 스프링이 제공하는 거라 학습테스트나 다름 없을 것 같아요. 무민이 질문해줘서 재밌게 읽었어요 . 감사합니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 나 왜 이렇게 |
||
|
||
@BeforeEach | ||
void setUp() { | ||
Objects.requireNonNull(cacheManager.getCache(CacheType.PET_FOODS.getName())).clear(); | ||
} | ||
|
||
@Nested | ||
class 필터_조회 { | ||
|
||
|
@@ -99,7 +118,7 @@ class 필터_조회 { | |
EMPTY_LIST | ||
), | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
//then | ||
|
@@ -143,7 +162,7 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
EMPTY_LIST | ||
), | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -183,7 +202,7 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
EMPTY_LIST | ||
), | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -226,7 +245,7 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
EMPTY_LIST | ||
), | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -266,7 +285,7 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
List.of("튼튼") | ||
), | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -307,7 +326,7 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
List.of("튼튼") | ||
), | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -340,14 +359,9 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
|
||
// when | ||
GetPetFoodsResponse petFoodsResponse = petFoodQueryService.getPetFoodsByFilters( | ||
FilterRequest.of( | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST | ||
), | ||
EMPTY_FILTER_REQUEST, | ||
lastPetFoodId, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -373,14 +387,9 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
|
||
// when | ||
GetPetFoodsResponse petFoodsResponse = petFoodQueryService.getPetFoodsByFilters( | ||
FilterRequest.of( | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST | ||
), | ||
EMPTY_FILTER_REQUEST, | ||
유럽_영양기준_만족_식품.getId() - 1, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -401,14 +410,9 @@ private Long getLastPetFoodId(List<PetFood> allFoods) { | |
|
||
// when | ||
GetPetFoodsResponse petFoodsResponse = petFoodQueryService.getPetFoodsByFilters( | ||
FilterRequest.of( | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST, | ||
EMPTY_LIST | ||
), | ||
EMPTY_FILTER_REQUEST, | ||
null, | ||
size | ||
SIZE | ||
); | ||
|
||
// then | ||
|
@@ -433,6 +437,44 @@ private boolean isLatest(long id, List<PetFoodResponse> petFoodResponses) { | |
return true; | ||
} | ||
|
||
@Test | ||
void 로컬_캐시가_있으면_로컬_캐시에서_데이터를_조회한다() { | ||
//given | ||
PetFood 모든_영양기준_만족_식품 = 모든_영양기준_만족_식품(brandRepository.save(아카나_식품_브랜드_생성())); | ||
식품_기능성_추가(모든_영양기준_만족_식품, functionalityRepository.save(기능성_튼튼())); | ||
식품_주원료_추가(모든_영양기준_만족_식품, primaryIngredientRepository.save(주원료_소고기())); | ||
petFoodRepository.save(모든_영양기준_만족_식품); | ||
|
||
// when | ||
GetPetFoodsResponse petFoodsResponse = petFoodQueryService.getPetFoodsByFilters( | ||
EMPTY_FILTER_REQUEST, | ||
null, | ||
SIZE | ||
); | ||
|
||
// then | ||
assertThat(petFoodsResponse).isEqualTo(getCachedPetFoodsResponse()); | ||
} | ||
|
||
private GetPetFoodsResponse getCachedPetFoodsResponse() { | ||
String key = FilterRequest.of(EMPTY_LIST, EMPTY_LIST, EMPTY_LIST, EMPTY_LIST) | ||
+ CACHE_KEY_DELIMITER + null + CACHE_KEY_DELIMITER + SIZE; | ||
return Objects.requireNonNull(cacheManager.getCache(CacheType.PET_FOODS.getName())) | ||
.get(key, GetPetFoodsResponse.class); | ||
} | ||
|
||
@Test | ||
void 로컬_캐시가_없으면_로컬_캐시에서_데이터를_조회하지_못한다() { | ||
//given | ||
PetFood 모든_영양기준_만족_식품 = 모든_영양기준_만족_식품(brandRepository.save(아카나_식품_브랜드_생성())); | ||
식품_기능성_추가(모든_영양기준_만족_식품, functionalityRepository.save(기능성_튼튼())); | ||
식품_주원료_추가(모든_영양기준_만족_식품, primaryIngredientRepository.save(주원료_소고기())); | ||
petFoodRepository.save(모든_영양기준_만족_식품); | ||
|
||
// then | ||
final GetPetFoodsResponse cachedPetFoodsResponse = getCachedPetFoodsResponse(); | ||
assertThat(cachedPetFoodsResponse).isNull(); | ||
} | ||
} | ||
|
||
@Nested | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
중요하지 않은 변경사항은 따로 커밋하면 좋은 것 같아요!
저도 이제 연습해보고 있는건데, 히스토리를 관리하는 센스가 중요한 것 같더라구요.
나중에 읽는 사람(높은 확률로 나 자신)한테 문서보다 훨씬 좋은 설명이기 때문에..
무민도 저와 함께 중요하고 관련있는 변경사항들이 히스토리에 같이 모여있을 수 있게 노력해봅시당