diff --git a/src/main/java/mju/iphak/maru_egg/question/application/QuestionProcessingService.java b/src/main/java/mju/iphak/maru_egg/question/application/QuestionProcessingService.java index 6272ea3..1d26eab 100644 --- a/src/main/java/mju/iphak/maru_egg/question/application/QuestionProcessingService.java +++ b/src/main/java/mju/iphak/maru_egg/question/application/QuestionProcessingService.java @@ -18,10 +18,11 @@ import mju.iphak.maru_egg.answer.dto.response.AnswerResponse; import mju.iphak.maru_egg.common.utils.NLP.TextSimilarityUtils; import mju.iphak.maru_egg.common.utils.PhraseExtractionUtils; +import mju.iphak.maru_egg.question.dao.request.SelectQuestionCores; +import mju.iphak.maru_egg.question.dao.response.QuestionCore; import mju.iphak.maru_egg.question.domain.Question; import mju.iphak.maru_egg.question.domain.QuestionCategory; import mju.iphak.maru_egg.question.domain.QuestionType; -import mju.iphak.maru_egg.question.dto.response.QuestionCore; import mju.iphak.maru_egg.question.dto.response.QuestionResponse; import mju.iphak.maru_egg.question.repository.QuestionRepository; @@ -39,7 +40,8 @@ public class QuestionProcessingService { public QuestionResponse question(final QuestionType type, final QuestionCategory category, final String content) { String contentToken = PhraseExtractionUtils.extractPhrases(content); - List questionCores = getQuestionCores(type, category, contentToken); + SelectQuestionCores selectQuestionCores = SelectQuestionCores.of(type, category, content, contentToken); + List questionCores = getQuestionCores(selectQuestionCores); if (questionCores.isEmpty()) { log.info("저장된 질문이 없어 새롭게 LLM서버에 질문을 요청합니다."); return answerManager.processNewQuestion(type, category, content, contentToken); @@ -59,12 +61,9 @@ public QuestionResponse getQuestion(final Long questionId) { return getExistingQuestionResponse(questionId); } - private List getQuestionCores(QuestionType type, QuestionCategory category, String contentToken) { - return category == null ? - questionRepository.searchQuestionsByContentTokenAndType(contentToken, type) - .orElse(Collections.emptyList()) : - questionRepository.searchQuestionsByContentTokenAndTypeAndCategory(contentToken, type, category) - .orElse(Collections.emptyList()); + private List getQuestionCores(SelectQuestionCores selectQuestionCores) { + return questionRepository.searchQuestions(selectQuestionCores) + .orElse(Collections.emptyList()); } private QuestionResponse getExistingQuestionResponse(Long questionId) { diff --git a/src/main/java/mju/iphak/maru_egg/question/application/QuestionService.java b/src/main/java/mju/iphak/maru_egg/question/application/QuestionService.java index 5b2c0df..0a94e57 100644 --- a/src/main/java/mju/iphak/maru_egg/question/application/QuestionService.java +++ b/src/main/java/mju/iphak/maru_egg/question/application/QuestionService.java @@ -17,6 +17,7 @@ import mju.iphak.maru_egg.answer.domain.Answer; import mju.iphak.maru_egg.answer.dto.response.AnswerResponse; import mju.iphak.maru_egg.common.dto.pagination.SliceQuestionResponse; +import mju.iphak.maru_egg.question.dao.request.SelectQuestions; import mju.iphak.maru_egg.question.domain.Question; import mju.iphak.maru_egg.question.domain.QuestionCategory; import mju.iphak.maru_egg.question.domain.QuestionType; @@ -47,18 +48,10 @@ public SliceQuestionResponse searchQuestionsOfCursorP final Integer size) { Pageable pageable = PageRequest.of(0, size); SliceQuestionResponse response; - response = questionRepository.searchQuestionsOfCursorPagingByContentWithLikeFunction( - type, - category, - content, - cursorViewCount, questionId, pageable); - if (response.data().isEmpty()) { - response = questionRepository.searchQuestionsOfCursorPagingByContentWithFullTextSearch( - type, - category, - content, - cursorViewCount, questionId, pageable); - } + + SelectQuestions selectQuestions = SelectQuestions.of(type, category, content, cursorViewCount, questionId, + pageable); + response = questionRepository.searchQuestionsOfCursorPaging(selectQuestions); return response; } diff --git a/src/main/java/mju/iphak/maru_egg/question/dao/request/SelectQuestionCores.java b/src/main/java/mju/iphak/maru_egg/question/dao/request/SelectQuestionCores.java new file mode 100644 index 0000000..f57dedc --- /dev/null +++ b/src/main/java/mju/iphak/maru_egg/question/dao/request/SelectQuestionCores.java @@ -0,0 +1,24 @@ +package mju.iphak.maru_egg.question.dao.request; + +import lombok.Builder; +import mju.iphak.maru_egg.question.domain.QuestionCategory; +import mju.iphak.maru_egg.question.domain.QuestionType; + +@Builder +public record SelectQuestionCores( + QuestionType type, + QuestionCategory category, + String content, + String contentToken +) { + + public static SelectQuestionCores of(final QuestionType type, final QuestionCategory category, final String content, + final String contentToken) { + return SelectQuestionCores.builder() + .type(type) + .category(category) + .content(content) + .contentToken(contentToken) + .build(); + } +} diff --git a/src/main/java/mju/iphak/maru_egg/question/dao/request/SelectQuestions.java b/src/main/java/mju/iphak/maru_egg/question/dao/request/SelectQuestions.java new file mode 100644 index 0000000..a0d4022 --- /dev/null +++ b/src/main/java/mju/iphak/maru_egg/question/dao/request/SelectQuestions.java @@ -0,0 +1,33 @@ +package mju.iphak.maru_egg.question.dao.request; + +import org.springframework.data.domain.Pageable; + +import lombok.Builder; +import mju.iphak.maru_egg.question.domain.QuestionCategory; +import mju.iphak.maru_egg.question.domain.QuestionType; + +@Builder +public record SelectQuestions( + QuestionType type, + QuestionCategory category, + String content, + Integer cursorViewCount, + Long questionId, + Pageable pageable +) { + public static SelectQuestions of(QuestionType type, + QuestionCategory category, + String content, + Integer cursorViewCount, + Long questionId, + Pageable pageable) { + return SelectQuestions.builder() + .type(type) + .category(category) + .content(content) + .cursorViewCount(cursorViewCount) + .questionId(questionId) + .pageable(pageable) + .build(); + } +} diff --git a/src/main/java/mju/iphak/maru_egg/question/dto/response/QuestionCore.java b/src/main/java/mju/iphak/maru_egg/question/dao/response/QuestionCore.java similarity index 89% rename from src/main/java/mju/iphak/maru_egg/question/dto/response/QuestionCore.java rename to src/main/java/mju/iphak/maru_egg/question/dao/response/QuestionCore.java index 5307618..6446629 100644 --- a/src/main/java/mju/iphak/maru_egg/question/dto/response/QuestionCore.java +++ b/src/main/java/mju/iphak/maru_egg/question/dao/response/QuestionCore.java @@ -1,4 +1,4 @@ -package mju.iphak.maru_egg.question.dto.response; +package mju.iphak.maru_egg.question.dao.response; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; diff --git a/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryCustom.java b/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryCustom.java index b12a742..86e8259 100644 --- a/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryCustom.java +++ b/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryCustom.java @@ -3,27 +3,15 @@ import java.util.List; import java.util.Optional; -import org.springframework.data.domain.Pageable; - import mju.iphak.maru_egg.common.dto.pagination.SliceQuestionResponse; -import mju.iphak.maru_egg.question.domain.QuestionCategory; -import mju.iphak.maru_egg.question.domain.QuestionType; -import mju.iphak.maru_egg.question.dto.response.QuestionCore; +import mju.iphak.maru_egg.question.dao.request.SelectQuestionCores; +import mju.iphak.maru_egg.question.dao.request.SelectQuestions; +import mju.iphak.maru_egg.question.dao.response.QuestionCore; import mju.iphak.maru_egg.question.dto.response.SearchedQuestionsResponse; public interface QuestionRepositoryCustom { - Optional> searchQuestionsByContentTokenAndType(final String contentToken, - final QuestionType type); - - Optional> searchQuestionsByContentTokenAndTypeAndCategory(final String contentToken, - final QuestionType type, - final QuestionCategory category); - - SliceQuestionResponse searchQuestionsOfCursorPagingByContentWithFullTextSearch( - final QuestionType type, final QuestionCategory category, final String content, - final Integer cursorViewCount, final Long questionId, final Pageable pageable); + Optional> searchQuestions(final SelectQuestionCores selectQuestionCores); - SliceQuestionResponse searchQuestionsOfCursorPagingByContentWithLikeFunction( - final QuestionType type, final QuestionCategory category, final String content, - final Integer cursorViewCount, final Long questionId, final Pageable pageable); + SliceQuestionResponse searchQuestionsOfCursorPaging( + final SelectQuestions selectQuestions); } \ No newline at end of file diff --git a/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImpl.java b/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImpl.java index 5f07848..30e30b3 100644 --- a/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImpl.java +++ b/src/main/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImpl.java @@ -2,6 +2,7 @@ import static mju.iphak.maru_egg.question.domain.QQuestion.*; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -19,10 +20,12 @@ import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import mju.iphak.maru_egg.common.dto.pagination.SliceQuestionResponse; +import mju.iphak.maru_egg.question.dao.request.SelectQuestionCores; +import mju.iphak.maru_egg.question.dao.request.SelectQuestions; +import mju.iphak.maru_egg.question.dao.response.QuestionCore; import mju.iphak.maru_egg.question.domain.Question; import mju.iphak.maru_egg.question.domain.QuestionCategory; import mju.iphak.maru_egg.question.domain.QuestionType; -import mju.iphak.maru_egg.question.dto.response.QuestionCore; import mju.iphak.maru_egg.question.dto.response.SearchedQuestionsResponse; @Repository @@ -33,42 +36,36 @@ public class QuestionRepositoryImpl implements QuestionRepositoryCustom { private final JPAQueryFactory queryFactory; - @Override - public Optional> searchQuestionsByContentTokenAndType(final String contentToken, - final QuestionType type) { - NumberTemplate booleanTemplate = createBooleanTemplate(contentToken); - List tuples = queryFactory.select(question.id, question.contentToken) - .from(question) - .where(booleanTemplate.gt(0).and(question.questionType.eq(type))) - .fetch(); - - List result = tuples.stream() - .map(tuple -> QuestionCore.of(tuple.get(question.id), tuple.get(question.contentToken))) - .collect(Collectors.toList()); - - return Optional.of(result); + public Optional> searchQuestions(final SelectQuestionCores selectQuestionCores) { + return Optional.of( + searchQuestionsByContentTokenAndType( + selectQuestionCores.content(), + selectQuestionCores.contentToken(), + selectQuestionCores.type(), + selectQuestionCores.category() + ).orElse(Collections.emptyList()) + ); } @Override - public Optional> searchQuestionsByContentTokenAndTypeAndCategory(final String contentToken, - final QuestionType type, final QuestionCategory category) { - NumberTemplate booleanTemplate = createBooleanTemplate(contentToken); - List tuples = queryFactory.select(question.id, question.contentToken) - .from(question) - .where(booleanTemplate.gt(0) - .and(question.questionType.eq(type)) - .and(question.questionCategory.eq(category))) - .fetch(); - - List result = tuples.stream() - .map(tuple -> QuestionCore.of(tuple.get(question.id), tuple.get(question.contentToken))) - .collect(Collectors.toList()); - - return Optional.of(result); + public SliceQuestionResponse searchQuestionsOfCursorPaging( + final SelectQuestions selectQuestions) { + SliceQuestionResponse response = searchQuestionsOfCursorPagingByContentWithLikeFunction( + selectQuestions.type(), + selectQuestions.category(), + selectQuestions.content(), + selectQuestions.pageable()); + if (response.data().isEmpty()) { + response = searchQuestionsOfCursorPagingByContentWithFullTextSearch( + selectQuestions.type(), + selectQuestions.category(), + selectQuestions.content(), + selectQuestions.cursorViewCount(), selectQuestions.questionId(), selectQuestions.pageable()); + } + return response; } - @Override - public SliceQuestionResponse searchQuestionsOfCursorPagingByContentWithFullTextSearch( + private SliceQuestionResponse searchQuestionsOfCursorPagingByContentWithFullTextSearch( final QuestionType type, final QuestionCategory category, final String content, final Integer cursorViewCount, final Long questionId, final Pageable pageable) { @@ -76,7 +73,7 @@ public SliceQuestionResponse searchQuestionsOfCursorP Integer viewCountCursorKey = getValidCursorViewCount(cursorViewCount); Long questionIdCursorKey = getValidCursorQuestionId(questionId); - NumberTemplate booleanTemplate = createBooleanTemplate(content); + NumberTemplate booleanTemplate = createBooleanTemplateByContentToken(content); BooleanExpression cursorPredicate = createCursorPredicate(viewCountCursorKey, questionIdCursorKey); List questions = fetchQuestions(type, category, booleanTemplate, cursorPredicate, pageSize); @@ -84,10 +81,8 @@ public SliceQuestionResponse searchQuestionsOfCursorP return buildSliceQuestionResponse(pageable, pageSize, questions); } - @Override - public SliceQuestionResponse searchQuestionsOfCursorPagingByContentWithLikeFunction( - final QuestionType type, final QuestionCategory category, final String content, - final Integer cursorViewCount, final Long questionId, final Pageable pageable) { + private SliceQuestionResponse searchQuestionsOfCursorPagingByContentWithLikeFunction( + final QuestionType type, final QuestionCategory category, final String content, final Pageable pageable) { int pageSize = pageable.getPageSize(); @@ -100,7 +95,47 @@ public SliceQuestionResponse searchQuestionsOfCursorP return buildSliceQuestionResponse(pageable, pageSize, questions); } - private NumberTemplate createBooleanTemplate(String content) { + private Optional> searchQuestionsByContentTokenAndType( + final String content, final String contentToken, final QuestionType type, final QuestionCategory category) { + + NumberTemplate booleanTemplate = createBooleanTemplateByContent(content); + + List tuples = fetchQuestionsByContentAndTypeAndCategory(booleanTemplate, type, category); + + if (tuples.isEmpty()) { + booleanTemplate = createBooleanTemplateByContentToken(contentToken); + tuples = fetchQuestionsByContentAndTypeAndCategory(booleanTemplate, type, category); + } + + List result = tuples.stream() + .map(tuple -> QuestionCore.of(tuple.get(question.id), tuple.get(question.contentToken))) + .collect(Collectors.toList()); + + return Optional.of(result); + } + + private List fetchQuestionsByContentAndTypeAndCategory( + NumberTemplate booleanTemplate, QuestionType type, QuestionCategory category) { + + BooleanBuilder whereClause = new BooleanBuilder(); + whereClause.and(booleanTemplate.gt(0)); + whereClause.and(question.questionType.eq(type)); + + if (category != null) { + whereClause.and(question.questionCategory.eq(category)); + } + + return queryFactory.select(question.id, question.contentToken) + .from(question) + .where(whereClause) + .fetch(); + } + + private NumberTemplate createBooleanTemplateByContentToken(String contentToken) { + return Expressions.numberTemplate(Double.class, "function('match', {0}, {1})", question.content, contentToken); + } + + private NumberTemplate createBooleanTemplateByContent(String content) { return Expressions.numberTemplate(Double.class, "function('match', {0}, {1})", question.content, content); } @@ -175,8 +210,7 @@ private SliceQuestionResponse buildSliceQuestionRespo } List questionResponses = questions.stream() - .map(q -> SearchedQuestionsResponse. - of(q.getId(), q.getContent(), q.isChecked())) + .map(q -> SearchedQuestionsResponse.of(q.getId(), q.getContent(), q.isChecked())) .collect(Collectors.toList()); Integer nextCursorViewCount = null; diff --git a/src/test/java/mju/iphak/maru_egg/question/application/QuestionProcessingServiceTest.java b/src/test/java/mju/iphak/maru_egg/question/application/QuestionProcessingServiceTest.java index 900e639..deaa3c4 100644 --- a/src/test/java/mju/iphak/maru_egg/question/application/QuestionProcessingServiceTest.java +++ b/src/test/java/mju/iphak/maru_egg/question/application/QuestionProcessingServiceTest.java @@ -37,10 +37,11 @@ import mju.iphak.maru_egg.answer.repository.AnswerRepository; import mju.iphak.maru_egg.common.MockTest; import mju.iphak.maru_egg.common.utils.PhraseExtractionUtils; +import mju.iphak.maru_egg.question.dao.request.SelectQuestionCores; +import mju.iphak.maru_egg.question.dao.response.QuestionCore; import mju.iphak.maru_egg.question.domain.Question; import mju.iphak.maru_egg.question.domain.QuestionCategory; import mju.iphak.maru_egg.question.domain.QuestionType; -import mju.iphak.maru_egg.question.dto.response.QuestionCore; import mju.iphak.maru_egg.question.dto.response.QuestionResponse; import mju.iphak.maru_egg.question.repository.QuestionRepository; import okhttp3.mockwebserver.MockResponse; @@ -87,16 +88,17 @@ void shutdown() throws IOException { @Test void 질문_조회_성공() { // given - QuestionType type = QuestionType.SUSI; - QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; String content = "테스트 질문입니다."; String contentToken = PhraseExtractionUtils.extractPhrases(content); + SelectQuestionCores selectQuestionCores = SelectQuestionCores.of(QuestionType.SUSI, + QuestionCategory.ADMISSION_GUIDELINE, content, contentToken); - when(questionRepository.searchQuestionsByContentTokenAndTypeAndCategory(anyString(), eq(type), eq(category))) + when(questionRepository.searchQuestions(eq(selectQuestionCores))) .thenReturn(Optional.of(List.of(QuestionCore.of(1L, contentToken)))); // when - QuestionResponse result = questionProcessingService.question(type, category, content); + QuestionResponse result = questionProcessingService.question(selectQuestionCores.type(), + selectQuestionCores.category(), content); // then assertThat(result).isEqualTo(createExpectedQuestionResponse()); @@ -106,20 +108,20 @@ void shutdown() throws IOException { @Test void 질문_없을_때_새로운_질문_요청() { // given - QuestionType type = QuestionType.SUSI; - QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; String content = "새로운 질문입니다."; + SelectQuestionCores selectQuestionCores = SelectQuestionCores.of(QuestionType.SUSI, + QuestionCategory.ADMISSION_GUIDELINE, content, content); String contentToken = PhraseExtractionUtils.extractPhrases(content); - when(questionRepository.searchQuestionsByContentTokenAndTypeAndCategory(eq(contentToken), eq(type), - eq(category))) + when(questionRepository.searchQuestions(eq(selectQuestionCores))) .thenReturn(Optional.of(Collections.emptyList())); // when - questionProcessingService.question(type, category, content); + questionProcessingService.question(selectQuestionCores.type(), selectQuestionCores.category(), content); // then - verify(answerManager, times(1)).processNewQuestion(eq(type), eq(category), eq(content), eq(contentToken)); + verify(answerManager, times(1)).processNewQuestion(eq(selectQuestionCores.type()), + eq(selectQuestionCores.category()), eq(content), eq(contentToken)); } @DisplayName("질문 조회 시 존재하지 않는 질문 ID로 인한 예외 처리") @@ -140,19 +142,19 @@ void shutdown() throws IOException { void 질문_검색_서버_내부_오류_빈배열_반환() { // given String contentToken = "서버 오류 테스트"; - QuestionType type = QuestionType.SUSI; - QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; + SelectQuestionCores selectQuestionCores = SelectQuestionCores.of(QuestionType.SUSI, + QuestionCategory.ADMISSION_GUIDELINE, contentToken, contentToken); List questionCores = List.of(); - when(questionRepository.searchQuestionsByContentTokenAndTypeAndCategory(eq(contentToken), eq(type), - eq(category))) + when(questionRepository.searchQuestions(eq(selectQuestionCores))) .thenReturn(Optional.of(questionCores)); // when - questionProcessingService.question(type, category, "서버 오류 테스트"); + questionProcessingService.question(selectQuestionCores.type(), selectQuestionCores.category(), "서버 오류 테스트"); // then - verify(answerManager, times(1)).processNewQuestion(eq(type), eq(category), eq("서버 오류 테스트"), eq(contentToken)); + verify(answerManager, times(1)).processNewQuestion(eq(selectQuestionCores.type()), + eq(selectQuestionCores.category()), eq("서버 오류 테스트"), eq(contentToken)); } @DisplayName("MOCK LLM 서버에 질문을 요청합니다.") @@ -192,8 +194,7 @@ private void setupMockEntities() { when(answerManager.getAnswerByQuestionId(1L)).thenReturn(answer); when(answerRepository.findByQuestionId(anyLong())).thenReturn(Optional.of(answer)); - when(questionRepository.searchQuestionsByContentTokenAndTypeAndCategory(anyString(), any(QuestionType.class), - any(QuestionCategory.class))) + when(questionRepository.searchQuestions(any(SelectQuestionCores.class))) .thenReturn(Optional.of(List.of(QuestionCore.of(1L, "테스트 질문입니다.")))); when(questionRepository.findById(1L)).thenReturn(Optional.of(question)); } diff --git a/src/test/java/mju/iphak/maru_egg/question/application/QuestionServiceTest.java b/src/test/java/mju/iphak/maru_egg/question/application/QuestionServiceTest.java index 465b639..7c75f85 100644 --- a/src/test/java/mju/iphak/maru_egg/question/application/QuestionServiceTest.java +++ b/src/test/java/mju/iphak/maru_egg/question/application/QuestionServiceTest.java @@ -38,11 +38,13 @@ import mju.iphak.maru_egg.answer.repository.AnswerRepository; import mju.iphak.maru_egg.common.MockTest; import mju.iphak.maru_egg.common.dto.pagination.SliceQuestionResponse; +import mju.iphak.maru_egg.question.dao.request.SelectQuestionCores; +import mju.iphak.maru_egg.question.dao.request.SelectQuestions; +import mju.iphak.maru_egg.question.dao.response.QuestionCore; import mju.iphak.maru_egg.question.domain.Question; import mju.iphak.maru_egg.question.domain.QuestionCategory; import mju.iphak.maru_egg.question.domain.QuestionType; import mju.iphak.maru_egg.question.dto.request.CreateQuestionRequest; -import mju.iphak.maru_egg.question.dto.response.QuestionCore; import mju.iphak.maru_egg.question.dto.response.QuestionListItemResponse; import mju.iphak.maru_egg.question.dto.response.SearchedQuestionsResponse; import mju.iphak.maru_egg.question.repository.QuestionRepository; @@ -81,8 +83,7 @@ void setUp() { when(answer.getId()).thenReturn(1L); when(answerManager.getAnswerByQuestionId(1L)).thenReturn(answer); when(answerRepository.findByQuestionId(anyLong())).thenReturn(Optional.of(answer)); - when(questionRepository.searchQuestionsByContentTokenAndTypeAndCategory(anyString(), any(QuestionType.class), - any(QuestionCategory.class))) + when(questionRepository.searchQuestions(any(SelectQuestionCores.class))) .thenReturn(Optional.of(List.of(QuestionCore.of(1L, "테스트 질문입니다.")))); when(questionRepository.findById(1L)).thenReturn(Optional.of(question)); questionService = new QuestionService(questionRepository, answerManager); @@ -144,27 +145,22 @@ void tearDown() throws IOException { String content = "example content"; Integer cursorViewCount = 0; Long questionId = 0L; - Integer size = 5; - QuestionType type = QuestionType.SUSI; - QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; + int size = 5; Pageable pageable = PageRequest.of(0, size); + SelectQuestions selectQuestions = SelectQuestions.of(QuestionType.SUSI, QuestionCategory.ADMISSION_GUIDELINE, + content, cursorViewCount, questionId, pageable); SearchedQuestionsResponse searchedQuestionsResponse = new SearchedQuestionsResponse(1L, "example content", true); SliceQuestionResponse expectedResponse = new SliceQuestionResponse<>( List.of(searchedQuestionsResponse), 0, size, false, null, null); - when(questionRepository.searchQuestionsOfCursorPagingByContentWithFullTextSearch(type, category, content, - cursorViewCount, - questionId, pageable)).thenReturn(expectedResponse); - - when(questionRepository.searchQuestionsOfCursorPagingByContentWithLikeFunction(type, category, content, - cursorViewCount, - questionId, pageable)).thenReturn(expectedResponse); + when(questionRepository.searchQuestionsOfCursorPaging(selectQuestions)).thenReturn(expectedResponse); // when - SliceQuestionResponse result = questionService.searchQuestionsOfCursorPaging(type, - category, content, + SliceQuestionResponse result = questionService.searchQuestionsOfCursorPaging( + selectQuestions.type(), + selectQuestions.category(), content, cursorViewCount, questionId, size); // then diff --git a/src/test/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImplTest.java b/src/test/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImplTest.java index e397cbf..ddf8175 100644 --- a/src/test/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImplTest.java +++ b/src/test/java/mju/iphak/maru_egg/question/repository/QuestionRepositoryImplTest.java @@ -23,11 +23,13 @@ import mju.iphak.maru_egg.answer.repository.AnswerRepository; import mju.iphak.maru_egg.common.RepositoryTest; import mju.iphak.maru_egg.common.dto.pagination.SliceQuestionResponse; +import mju.iphak.maru_egg.question.dao.request.SelectQuestionCores; +import mju.iphak.maru_egg.question.dao.request.SelectQuestions; +import mju.iphak.maru_egg.question.dao.response.QuestionCore; import mju.iphak.maru_egg.question.domain.QQuestion; import mju.iphak.maru_egg.question.domain.Question; import mju.iphak.maru_egg.question.domain.QuestionCategory; import mju.iphak.maru_egg.question.domain.QuestionType; -import mju.iphak.maru_egg.question.dto.response.QuestionCore; import mju.iphak.maru_egg.question.dto.response.SearchedQuestionsResponse; class QuestionRepositoryImplTest extends RepositoryTest { @@ -109,7 +111,7 @@ public void setUp() throws Exception { QQuestion question = QQuestion.question; String contentToken = "수시 입학 요강 대해"; QuestionType type = QuestionType.SUSI; - NumberTemplate numberTemplate = createBooleanTemplate(question, contentToken); + NumberTemplate numberTemplate = createBooleanTemplateByContentToken(question, contentToken); // when List results = queryFactory.selectFrom(question) @@ -126,11 +128,11 @@ public void setUp() throws Exception { void contentToken_type으로_질문_검색_실패() { // given String invalidContentToken = "잘못된 질문"; - QuestionType type = QuestionType.SUSI; + SelectQuestionCores selectQuestionCores = SelectQuestionCores.of(QuestionType.SUSI, null, invalidContentToken, + invalidContentToken); // when - Optional> result = questionRepositoryImpl.searchQuestionsByContentTokenAndType( - invalidContentToken, type); + Optional> result = questionRepositoryImpl.searchQuestions(selectQuestionCores); // then assertThat(result).isPresent(); @@ -145,7 +147,7 @@ public void setUp() throws Exception { String contentToken = "수시 입학 요강 대해"; QuestionType type = QuestionType.SUSI; QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; - NumberTemplate numberTemplate = createBooleanTemplate(question, contentToken); + NumberTemplate numberTemplate = createBooleanTemplateByContentToken(question, contentToken); // when List results = queryFactory.select(question.contentToken) @@ -165,12 +167,12 @@ public void setUp() throws Exception { void contentToken_type_Category로_질문_검색_실패() { // given String invalidContentToken = "잘못된 질문"; - QuestionType type = QuestionType.SUSI; - QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; + SelectQuestionCores selectQuestionCores = SelectQuestionCores.of(QuestionType.SUSI, + QuestionCategory.ADMISSION_GUIDELINE, invalidContentToken, + invalidContentToken); // when - Optional> result = questionRepositoryImpl.searchQuestionsByContentTokenAndTypeAndCategory( - invalidContentToken, type, category); + Optional> result = questionRepositoryImpl.searchQuestions(selectQuestionCores); // then assertThat(result).isPresent(); @@ -182,13 +184,13 @@ public void setUp() throws Exception { void content로_질문_페이지네이션_조회_실패() { // given String content = "존재하지 않는 질문"; - QuestionType type = QuestionType.SUSI; - QuestionCategory category = QuestionCategory.ADMISSION_GUIDELINE; Pageable pageable = PageRequest.of(0, 3); + SelectQuestions selectQuestions = SelectQuestions.of(QuestionType.SUSI, QuestionCategory.ADMISSION_GUIDELINE, + content, null, null, pageable); // when - SliceQuestionResponse result = questionRepositoryImpl.searchQuestionsOfCursorPagingByContentWithFullTextSearch( - type, category, content, null, null, pageable); + SliceQuestionResponse result = questionRepositoryImpl.searchQuestionsOfCursorPaging( + selectQuestions); // then assertThat(result.data()).isEmpty(); @@ -199,7 +201,7 @@ void contentToken_type() { QQuestion question = QQuestion.question; String contentToken = "수시 입학 요강 대해"; QuestionType type = QuestionType.SUSI; - NumberTemplate numberTemplate = createBooleanTemplate(question, contentToken); + NumberTemplate numberTemplate = createBooleanTemplateByContentToken(question, contentToken); List results = queryFactory.select(question.contentToken) .from(question) @@ -216,7 +218,7 @@ void contentToken_type() { QQuestion question = QQuestion.question; String contentToken = "수시 입학 요강 대해"; - NumberTemplate numberTemplate = createBooleanTemplate(question, contentToken); + NumberTemplate numberTemplate = createBooleanTemplateByContentToken(question, contentToken); // when List results = queryFactory.selectFrom(question) @@ -233,7 +235,7 @@ void contentToken_type() { // given QQuestion question = QQuestion.question; String invalidContentToken = "존재하지 않는 질문"; - NumberTemplate numberTemplate = createBooleanTemplate(question, invalidContentToken); + NumberTemplate numberTemplate = createBooleanTemplateByContentToken(question, invalidContentToken); // when List results = queryFactory.selectFrom(question) @@ -244,7 +246,7 @@ void contentToken_type() { assertThat(results).isEmpty(); } - private NumberTemplate createBooleanTemplate(QQuestion question, String content) { + private NumberTemplate createBooleanTemplateByContentToken(QQuestion question, String content) { return Expressions.numberTemplate(Double.class, "function('match', {0}, {1})", question.content, content); } } \ No newline at end of file