์ค๋ ์งํํ ๋ด์ฉ๋ค ๐ง
ํ ์คํธ ์ฝ๋ ์์ฑํ๊ธฐ
searchHistoryTaskHendler
package com.project.cheerha.domain.searchhistory.scheduler;
import com.project.cheerha.domain.searchhistory.entity.SearchHistory;
import com.project.cheerha.domain.searchhistory.repository.SearchHistoryRepository;
import com.project.cheerha.domain.user.entity.User;
import com.project.cheerha.domain.user.service.UserFindByService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
public class SearchHistoryTaskHandlerTest {
@InjectMocks
private SearchHistoryTaskHandler searchHistoryTaskHandler;
@Mock
private UserFindByService userFindByService;
@Mock
private SearchHistoryRepository searchHistoryRepository;
@Mock
private RedisTemplate<String, String> redisTemplate;
@Mock
private ZSetOperations<String, String> zSetOperations;
@Captor
private ArgumentCaptor<List<SearchHistory>> searchHistoryCaptor;
@BeforeEach
void setUp() {
when(redisTemplate.opsForZSet()).thenReturn(zSetOperations);
}
@Test
@DisplayName("Redis์ ๊ฒ์ ๊ธฐ๋ก์ด ์กด์ฌํ๊ณ ์ค๋ณต๋์ง ์์ ๊ฒ์์ด๊ฐ ์์ผ๋ฉด DB์ ์ ์ฅ")
void Redis์_์ค๋ณต๋์ง_์์_๊ฒ์์ด_์์ผ๋ฉด_DB_์ ์ฅ() {
// given
Long userId = 1L;
String key = "user:" + userId + ":search_history";
User mockUser = User.toEntity("test@gmail.com", "์ฌ์ฉ์", 27, 1, "password123");
Set<String> redisSearchTermSet = new HashSet<>(Set.of("Elasticsearch", "Docker"));
Set<String> existinfSearchTermSet = new HashSet<>(Set.of("Elasticsearch"));
when(redisTemplate.keys("user:*:search_history")).thenReturn(Set.of(key));
when(userFindByService.findById(userId)).thenReturn(mockUser);
when(zSetOperations.range(key, 0, -1)).thenReturn(redisSearchTermSet);
when(searchHistoryRepository.findNamesByUserId(userId)).thenReturn(existinfSearchTermSet);
// when
searchHistoryTaskHandler.handle(Collections.emptyMap());
// then
verify(searchHistoryRepository, times(1)).saveAll(searchHistoryCaptor.capture());
List<SearchHistory> capturedList = searchHistoryCaptor.getValue();
assertThat(capturedList).hasSize(1);
assertThat(capturedList.get(0).getName()).isEqualTo("Docker");
}
@Test
@DisplayName("Redis์ ๊ฒ์ ๊ธฐ๋ก์ด ์์ง๋ง ๋ชจ๋ ์ค๋ณต๋ ๊ฒฝ์ฐ DB์ ์ ์ฅํ์ง ์์")
void Redis์_๊ฒ์_๊ธฐ๋ก์ด_์์ง๋ง_์ค๋ณต๋_๊ฒฝ์ฐ_DB์_์ ์ฅํ์ง_์์() {
// given
Long userId = 2L;
String key = "user:" + userId + ":search_history";
User mockUser = User.toEntity("test2@gmail.com", "์ฌ์ฉ์2", 25, 3, "password123");
Set<String> redisSearchTermSet = new HashSet<>(Set.of("Elasticsearch", "Spring"));
Set<String> existingSearchTermSet = new HashSet<>(Set.of("Elasticsearch", "Spring"));
when(redisTemplate.keys("user:*:search_history")).thenReturn(Set.of(key));
when(userFindByService.findById(userId)).thenReturn(mockUser);
when(zSetOperations.range(key, 0, -1)).thenReturn(redisSearchTermSet);
when(searchHistoryRepository.findNamesByUserId(userId)).thenReturn(existingSearchTermSet);
// when
searchHistoryTaskHandler.handle(Collections.emptyMap());
// then
verify(searchHistoryRepository, never()).saveAll(any());
}
}
์ต์ข ํ๋ก์ ํธ ๋ธ๋ก์ ์์ฑํ๊ธฐ
๋ด๊ฐ ์งํํ๋ ๋ถ๋ถ์ ๋ธ๋ก์
์ ์ฑ์๋ฃ์๋ค!
๋ฌธ์ํ๋ฅผ ๋ค ํด๋จ์ด๋ ๊ธ์ ์์ฑํ๋ ๊ฒ์ด ์ด๋ ๊ฒ ์ด๋ ต๋ค๋ ๊ฒ์ ๋ค์ ํ๋ฒ ๊นจ๋ซ๋ ์๊ฐ์ด์๋ค..
์ค๋ ํ๋ฃจ ์ ๋ฆฌ ๐
์ค๋๋ง์ ์ ์ด๋ณด๋ ํ๋ฃจ ์ ๋ฆฌ..
์ต๊ทผ์ ์ต์ข
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ๋๋ฌด ์ ์ ์ด ์์๊ณ , ํ๋ฃจ ์ ๋ฆฌํ๋ ๋ง์ ์ ์ ์๊ฐ๋ ์์๋ ๊ฒ ๊ฐ๋ค.. (์ฌ์ค ์ ์ ์๊ฐ์ด ์์๋ค๋ ๊ฑด ํ๊ณ์ผ ์๋ ์๋ค..ใ
ใ
)
์ต์ข
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์ข์ ํ์๋ถ๋ค๊ณผ ํจ๊ป ํ์
ํ๋ฉด์ ๋ ์ค์ค๋ก๋ ๋ง์ด ์ฑ์ฅํ ์๊ฐ์ด์๋ ๊ฒ ๊ฐ๋ค.
CRUD๋ง ๊ตฌํํ ์ค ์๋ ๋ด๊ฐ Elasticsearch๋ฅผ ์ฌ์ฉํ๊ณ ์๊ณ , ํ์ํ ๊ธฐ๋ฅ์ ์ด๋ป๊ฒ๋ ๊ตฌํํด๋ด๊ณ ์์ผ๋๊น!!
๋ฌผ๋ก ์์ง ๋ถ์กฑํ ์ ์ด ๋ง๋ค๊ณ ์๊ฐํ๋ค. AWS ๊ด๋ จ ์ง์๋ ๊ฑฐ์ ์๊ณ , CI/CD์ ๋ํ ๊ฐ๋
๋ ์๋ค. ์ด๋ฐ ๋ถ๋ถ์ ์ต์ข
ํ๋ก์ ํธ๊ฐ ๋๋๊ณ ๋๋ฉด ํ์ตํ๋ ์๊ฐ์ ๋ฐ๋ก ๋ง๋ค์ด์ ๊ณต๋ถํด์ผ ํ ๊ฒ ๊ฐ๋ค.
CRUD๋ง ๊ตฌํํ๋ ํ๋ก์ ํธ๋ค์ ํ์ ๋๋ "์ด๊ฒ๋ง ๊ตฌํํ๋ฉด ๋๋๊ตฌ๋!" ๋ผ๊ณ ์๊ฐํ์๋๋ฐ ์ฐ๋ฌผ ์ ๊ฐ๊ตฌ๋ฆฌ์๋ค..
๊ทธ ๋ค์๋ ์์ฒญ๋๊ฒ ๋ง์ ๊ธฐ์ ์คํ๊ณผ ๊ฐ๋
๋ค์ด ์จ์ด์์๋ค.
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ๊ธฐ๋กํด๋ "5๋ถ ๊ธฐ๋ก ๋ณด๋"์ "๊ฐ๋ฐ ์ผ์ง"๋ฅผ ํ์ฉํด์ ํ๋ก์ ํธ๊ฐ ๋๋๋ฉด ๋ค์ ํ๋ฒ ๋ด๊ฐ ํ ๋ด์ฉ๋ค์ ๋ณต์ตํ๊ณ ์ ๋ฆฌํ๋ ์๊ฐ๋ ๊ฐ์ ธ์ผ ํ ๊ฒ ๊ฐ๋ค.
๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๋ด๊ฐ ํ ๋ด์ฉ์ ๊น๋จน์ง ์๋ ๊ฒ์ด๋ค. ๊ธฐ์ต๋ ฅ์ด ์ต๋ํ ์ด์์์ ๋ ํ๋ฒ ๋ ์ ๋ฆฌํ๋ฉด์ ๋ด์ฉ๋ค์ ๋ณต์ตํ๊ณ ์ ๋ฆฌํ๋ฉด ๋จธ๋ฆฌ์ ๋ ์ ๋จ์ ๊ฒ์ด๋ค.
๋ญ๊ฐ ์์ฆ ํํ๋ ๊ณ์ ์ฐพ์์ค๊ณ ๋ฌด๊ธฐ๋ ฅํ ๋ ๋ค์ด ๊ณ์๋๊ณ ์๋ค..
๋ญ๊ฐ ์์กด๊ฐ๋ ๋ฎ์์ง๊ณ .. ๋ด๊ฐ ๊ณผ์ฐ ์ทจ์
์ ํ ์ ์์๊น?? ํ๋ ์๋ฌธ์ด ๊ฐ๋ํด์ง๊ณ ์๋ค.
๊ต์ก์ ๊ฐ์ด ๋ฃ๋ ์ฌ๋๋ค์ "๋์๊ฒ ์ฑ์คํ๋๊น ์ํ ๊ฒ์ด๋ค.", "์ง๊ธ๋ ์ถฉ๋ถํ ์ํ๊ณ ์๋ค.", "์ง๊ธ์ฒ๋ผ ๊พธ์คํ ๋
ธ๋ ฅํ๋ค๋ฉด ๋ฌด์กฐ๊ฑด ๊ฐ๋ฅํ๋ค." ๋ผ๋ ๋ง์ ํด์ฃผ์์ง๋ง ์ ์ ๋๋ ๊ณ์ ์์ ๊ฐ..? ์์กด๊ฐ..? ์ด ๋ฎ์์ง๋ ๊ฒ ๊ฐ๋ค.
์ผ๋ฅธ ๊ธฐ์ด์ ์ฐจ๋ฆฌ๊ณ ๋ค์ ์ด์ฌํ ํด์ผ ํ๋๋ฐ.. ์๊ฐ๋ณด๋ค ์ฝ์ง ์์ ๊ฒ ๊ฐ๋ค์ผ์์์..
๋
ธ๋๋ฅผ ๋ค์ผ๋ฉด์ ์ ๋ค ๋ณด๋๊น ๊ฐ์ฑ์ ์ผ๋ก ๋ณํด์ ๋ญ๊ฐ ๋ ์ ์ ๊ฒ ๊ฐ์๋ฐ..
์ผ๋ฅธ ๋ค์ ํ์ ๋ด๊ณ ๊พธ์คํ๊ฒ ๊ณต๋ถํ ์ ์๋ ํ๊ฒฝ์ ๋ง๋ค์ด์ผ๊ฒ ๋ค.
ํ๋ก์ ํธ๊ฐ ๋๋๊ฐ๋ค๊ณ ์์ฌํ๊ณ ์์ผ๋ฉด ์๋๋ค!!
์ทจ์ ํ๊ฒ ๋๋ ๊ทธ๋ ๊น์ง.. ํ์ ๋ด๋ณด์!! ํ์ดํ !!!
๋ด์ผ ๊ณํ โฐ
- ๋ธ๋ก์ ์์ฑํ๊ธฐ
+ ์ถ๊ฐ ๊ณํ์ด ์๊ธธ ์๋ ์์ต๋๋ค~_~
'๐ฅ๏ธ ์ต์ข ํ๋ก์ ํธ > โ๏ธ TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ TIL ] ์ต์ข ํ๋ก์ ํธ_Day 33 (2) | 2025.03.15 |
---|---|
[ TIL ] ์ต์ข ํ๋ก์ ํธ_Day 29 (1) | 2025.03.11 |
[ TIL ] ์ต์ข ํ๋ก์ ํธ_Day26 (1) | 2025.03.08 |
[ TIL ] ์ต์ข ํ๋ก์ ํธ_Day 25 (1) | 2025.03.06 |
[ TIL ] ์ต์ข ํ๋ก์ ํธ_Day 24 (0) | 2025.03.05 |