diff --git a/src/main/java/com/ureca/ufit/domain/admin/dto/response/AdminRatePlanResponse.java b/src/main/java/com/ureca/ufit/domain/admin/dto/response/AdminRatePlanResponse.java index b50cd9f..53945a3 100644 --- a/src/main/java/com/ureca/ufit/domain/admin/dto/response/AdminRatePlanResponse.java +++ b/src/main/java/com/ureca/ufit/domain/admin/dto/response/AdminRatePlanResponse.java @@ -7,16 +7,16 @@ public record AdminRatePlanResponse( String ratePlanId, String planName, String summary, - int monthlyFee, - int discountFee, + Integer monthlyFee, + Integer discountFee, String dataAllowance, String voiceAllowance, String smsAllowance, Map basicBenefit, Map specialBenefit, Map discountBenefit, - boolean isEnabled, - boolean isDeleted, + Boolean isEnabled, + Boolean isDeleted, LocalDateTime createdAt ) { } diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/client/ChatClient.java b/src/main/java/com/ureca/ufit/domain/chatbot/client/ChatClient.java new file mode 100644 index 0000000..09bfc17 --- /dev/null +++ b/src/main/java/com/ureca/ufit/domain/chatbot/client/ChatClient.java @@ -0,0 +1,8 @@ +package com.ureca.ufit.domain.chatbot.client; + +import com.ureca.ufit.domain.chatbot.dto.request.CreateUserQuerySummaryRequest; +import com.ureca.ufit.domain.chatbot.dto.response.QuestionSummaryDto; + +public interface ChatClient { + QuestionSummaryDto getSummary(CreateUserQuerySummaryRequest request, long chatRoomId); +} \ No newline at end of file diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java index 2f25906..bcae2f2 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotController.java @@ -1,5 +1,7 @@ package com.ureca.ufit.domain.chatbot.controller; +import java.util.concurrent.CompletableFuture; + import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -50,12 +52,14 @@ public ResponseEntity createChatBotReview(CreateCha } @Override - public ResponseEntity createChatBotMessage(CustomUserDetails userDetails, + public ResponseEntity> createChatBotMessage( + CustomUserDetails userDetails, CreateChatBotMessageRequest request) { Long userId = (userDetails != null) ? userDetails.userId() : nonUserId; - CreateChatBotMessageResponse response = chatBotMessageService.createChatBotMessage(request, userId); + CompletableFuture response = chatBotMessageService.createChatBotMessage(request, + userId); return ResponseEntity.status(HttpStatus.CREATED).body(response); } diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java index 7e0787a..97269c4 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/controller/ChatBotControllerApiSpec.java @@ -1,5 +1,7 @@ package com.ureca.ufit.domain.chatbot.controller; +import java.util.concurrent.CompletableFuture; + import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; @@ -107,7 +109,7 @@ public ResponseEntity createChatBotReview( content = @Content(schema = @Schema(implementation = CreateChatBotMessageResponse.class)) )) @PostMapping("/message") - public ResponseEntity createChatBotMessage( + public ResponseEntity> createChatBotMessage( @Parameter(hidden = true) @AuthenticationPrincipal CustomUserDetails userDetails, @RequestBody @Valid CreateChatBotMessageRequest request diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java index d250ce8..068eda7 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotMessageService.java @@ -3,6 +3,7 @@ import static com.ureca.ufit.global.profanity.BanwordFilterPolicy.*; import java.util.Set; +import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Pageable; @@ -45,7 +46,8 @@ public CursorPageResponse getChatMessages(Long chatRoomId, Pagea } @Async - public CreateChatBotMessageResponse createChatBotMessage(CreateChatBotMessageRequest request, Long userId) { + public CompletableFuture createChatBotMessage(CreateChatBotMessageRequest request, + Long userId) { Set policies = Set.of(NUMBERS, WHITESPACES); @@ -58,11 +60,12 @@ public CreateChatBotMessageResponse createChatBotMessage(CreateChatBotMessageReq CreateAIAnswerRequest createAIAnswerRequest = ChatMessageMapper.toCreateAIAnswerRequest(request, userId); try { - return restTemplate.postForObject( + CreateChatBotMessageResponse response = restTemplate.postForObject( fastApiUrl, createAIAnswerRequest, CreateChatBotMessageResponse.class ); + return CompletableFuture.completedFuture(response); } catch (Exception e) { throw new RestApiException(ChatBotErrorCode.LLM_TIMEOUT); diff --git a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java index 95ec217..4290da0 100644 --- a/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java +++ b/src/main/java/com/ureca/ufit/domain/chatbot/service/ChatBotReviewService.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClient; import org.springframework.web.client.RestTemplate; import com.ureca.ufit.domain.admin.dto.ChatBotReviewMapper; @@ -73,8 +74,15 @@ private QuestionSummaryDto requestUserQuerySummary(CreateChatBotReviewRequest re CreateUserQuerySummaryRequest chatReviewSummaryRequest = new CreateUserQuerySummaryRequest( request.recommendationMessageId()); - QuestionSummaryDto questionSummaryDto = restTemplate.postForObject(url, chatReviewSummaryRequest, - QuestionSummaryDto.class); + // QuestionSummaryDto questionSummaryDto = restTemplate.postForObject(url, chatReviewSummaryRequest, + // QuestionSummaryDto.class); + + RestClient restClient = RestClient.create(); + QuestionSummaryDto questionSummaryDto = restClient.post() + .uri(url) + .body(chatReviewSummaryRequest) + .retrieve() + .body(QuestionSummaryDto.class); validateSummary(questionSummaryDto); return questionSummaryDto; diff --git a/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java b/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java index 0967c2a..39afeca 100644 --- a/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java +++ b/src/main/java/com/ureca/ufit/global/auth/handler/CustomLogoutHandler.java @@ -42,22 +42,33 @@ public void logout(HttpServletRequest request, HttpServletResponse response, throw new RestApiException(CommonErrorCode.NOT_EXIST_BEARER_SUFFIX); } String accessToken = bearerToken.substring(BEARER_PREFIX.length()); - JwtUtil.validateAccessToken(accessToken, secretKey); - // 블랙 리스트에 어세스 토큰 추가 - addToBlacklistRedis(accessToken); + try { + JwtUtil.validateAccessToken(accessToken, secretKey); - // 레디스에서 리프레시 토큰 삭제 - String refreshToken = JwtUtil.getRefreshTokenCookies(request); - if (refreshToken != null) { - // Redis에서 해당 리프레시 토큰 키 삭제 - refreshTokenRepository.findById(refreshToken) - .ifPresent(refreshTokenRepository::delete); + // 블랙 리스트에 어세스 토큰 추가 + addToBlacklistRedis(accessToken); + } catch (RestApiException e) { + // 어세스토큰 만료는 정상 처리 + if( !e.getErrorCode().equals(CommonErrorCode.EXPIRED_TOKEN)) + throw e; } + String refreshToken = JwtUtil.getRefreshTokenCookies(request); // 쿠키에서 리프레시 토큰 삭제 (timeout을 0으로 두어 즉시 삭제) JwtUtil.updateRefreshTokenCookie(response, null, 0); + + // Redis에서 해당 리프레시 토큰 키 삭제 + refreshTokenRepository.delete( + refreshTokenRepository.findById(refreshToken).orElseThrow( () -> + new RestApiException(CommonErrorCode.REFRESH_NOT_FOUND) + ) + ); + } catch (RestApiException e) { + // 쿠키나 레디스에서 리프레시 토큰을 찾지 못했을 경우 정상처리 + if(e.getErrorCode().equals(CommonErrorCode.REFRESH_NOT_FOUND)) + return; try { SendErrorResponseUtil.sendErrorResponse(response, e.getErrorCode()); } catch (IOException ex) { diff --git a/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java b/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java index 433fb5a..9d6e017 100644 --- a/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java +++ b/src/main/java/com/ureca/ufit/global/auth/util/JwtUtil.java @@ -155,7 +155,7 @@ public static String getRefreshTokenCookies(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if (cookies == null) - throw new RestApiException(CommonErrorCode.REFRESH_DENIED); + throw new RestApiException(CommonErrorCode.REFRESH_NOT_FOUND); for (Cookie cookie : cookies) { if (REFRESH_TOKEN_COOKIE_NAME.equals(cookie.getName())) { @@ -163,7 +163,7 @@ public static String getRefreshTokenCookies(HttpServletRequest request) { } } - throw new RestApiException(CommonErrorCode.REFRESH_DENIED); + throw new RestApiException(CommonErrorCode.REFRESH_NOT_FOUND); } } \ No newline at end of file diff --git a/src/test/java/com/ureca/ufit/chatbot/service/ChatBotReviewServiceTest.java b/src/test/java/com/ureca/ufit/chatbot/service/ChatBotReviewServiceTest.java index 367b640..0ce1607 100644 --- a/src/test/java/com/ureca/ufit/chatbot/service/ChatBotReviewServiceTest.java +++ b/src/test/java/com/ureca/ufit/chatbot/service/ChatBotReviewServiceTest.java @@ -1,233 +1,242 @@ -package com.ureca.ufit.chatbot.service; - -import static com.ureca.ufit.domain.chatbot.exception.ChatBotErrorCode.*; -import static java.lang.Boolean.*; -import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.BDDMockito.*; - -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.web.client.RestTemplate; - -import com.ureca.ufit.common.fixture.ChatBotReviewFixture; -import com.ureca.ufit.domain.chatbot.dto.request.CreateChatBotReviewRequest; -import com.ureca.ufit.domain.chatbot.dto.request.CreateUserQuerySummaryRequest; -import com.ureca.ufit.domain.chatbot.dto.response.CreateChatBotReviewResponse; -import com.ureca.ufit.domain.chatbot.dto.response.QuestionSummaryDto; -import com.ureca.ufit.domain.chatbot.repository.ChatBotReviewRepository; -import com.ureca.ufit.domain.chatbot.service.ChatBotMessageService; -import com.ureca.ufit.domain.chatbot.service.ChatBotReviewService; -import com.ureca.ufit.domain.chatbot.service.ChatRoomService; -import com.ureca.ufit.entity.ChatBotReview; -import com.ureca.ufit.global.exception.RestApiException; -import com.ureca.ufit.global.profanity.ProfanityService; - -@ExtendWith(MockitoExtension.class) -class ChatBotReviewServiceTest { - - @Mock - RestTemplate restTemplate; - @Mock - ChatBotReviewRepository chatBotReviewRepository; - @Mock - ProfanityService profanityService; - @Mock - ChatRoomService chatRoomService; - @Mock - ChatBotMessageService chatBotMessageService; - @InjectMocks - ChatBotReviewService chatBotReviewService; - - @DisplayName("챗봇 리뷰를 저장한다.") - @Test - void savedChatBotReview() { - // given - final String CHAT_REVIEW_SUCCESS_MSG = "리뷰가 정상적으로 제출되었습니다."; - - CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( - 1, - "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", - Map.of( - "recommandPlans", - List.of( - Map.of("aPlan", "5G 무제한"), - Map.of("bPlan", "내맘대로 5G 요금제") - ) - ), - 1L, - "684d9a790eea0b57af47a8d1" - ); - QuestionSummaryDto questionSummaryDto = new QuestionSummaryDto("데이터 많은 요금제 추천해줘"); - ChatBotReview chatBotReview = ChatBotReviewFixture.chatBotReview( - request.content(), - questionSummaryDto.summary() - ); - - given(restTemplate.postForObject( - anyString(), - any(CreateUserQuerySummaryRequest.class), - eq(QuestionSummaryDto.class) - )).willReturn(questionSummaryDto); - given(chatBotReviewRepository.save(any(ChatBotReview.class))).willReturn(chatBotReview); - - // when - CreateChatBotReviewResponse response = chatBotReviewService.createChatBotReview(request); - - // then - assertAll( - () -> assertThat(response.message()).isEqualTo(CHAT_REVIEW_SUCCESS_MSG), - () -> verify(chatBotReviewRepository).save(any(ChatBotReview.class)), - () -> verify(restTemplate).postForObject( - anyString(), - any(CreateUserQuerySummaryRequest.class), - eq(QuestionSummaryDto.class)) - ); - } - - @DisplayName("채팅방ID가 유효하지 않은 리뷰는 저장할 수 없다.") - @Test - void throwExceptionWhenChatRoomIdIsInvalid() { - // given - CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( - 1, - "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", - Map.of( - "recommandPlans", - List.of( - Map.of("aPlan", "5G 무제한"), - Map.of("bPlan", "내맘대로 5G 요금제") - ) - ), - 1L, - "684d9a790eea0b57af47a8d1" - ); - - doThrow(new RestApiException(CHATROOM_NOT_FOUND)) - .when(chatRoomService) - .getValidatedChatRoom(anyLong()); - - // when // then - assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) - .isInstanceOf(RestApiException.class) - .hasMessage(CHATROOM_NOT_FOUND.getMessage()); - } - - @DisplayName("리뷰 메시지와 채팅방이 일치하지 않으면 리뷰를 저장할 수 없다.") - @Test - void throwExceptionWhenChatBotMessageNotMatchChatRoom() { - // given - CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( - 1, - "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", - Map.of( - "recommandPlans", - List.of( - Map.of("aPlan", "5G 무제한"), - Map.of("bPlan", "내맘대로 5G 요금제") - ) - ), - 1L, - "684d9a790eea0b57af47a8d1" - ); - - doThrow(new RestApiException(INVALID_CHATBOT_MESSAGE)) - .when(chatBotMessageService) - .validateMessageBelongsToChatRoom(anyString(), anyLong()); - - // when // then - assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) - .isInstanceOf(RestApiException.class) - .hasMessage(INVALID_CHATBOT_MESSAGE.getMessage()); - } - - @DisplayName("챗봇 리뷰 내용에 금칙어가 포함되어 있으면 저장할 수 없다.") - @Test - void throwExceptionWhenChatBotReviewContentIsProfanity() { - // given - CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( - 1, - "추천 퀄리티가 존나 좋네요 ㅋㅋ", - Map.of( - "recommandPlans", - List.of( - Map.of("aPlan", "5G 무제한"), - Map.of("bPlan", "내맘대로 5G 요금제") - ) - ), - 1L, - "684d9a790eea0b57af47a8d1" - ); - - given(chatBotReviewRepository.existsByChatBotMessageId(anyString())).willReturn(FALSE); - given(profanityService.containsBannedWord(anyString(), anySet())).willReturn(TRUE); - - // when // then - assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) - .isInstanceOf(RestApiException.class) - .hasMessage(CONTENT_RESTRICTED_WORD.getMessage()); - } - - @DisplayName("챗봇 리뷰를 중복해서 저장할 수 없다.") - @Test - void throwExceptionWhenChatBotReviewIsDuplicated() { - // given - CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( - 1, - "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", - Map.of( - "recommandPlans", - List.of( - Map.of("aPlan", "5G 무제한"), - Map.of("bPlan", "내맘대로 5G 요금제") - ) - ), - 1L, - "684d9a790eea0b57af47a8d1" - ); - - given(chatBotReviewRepository.existsByChatBotMessageId(anyString())).willReturn(TRUE); - - // when // then - assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) - .isInstanceOf(RestApiException.class) - .hasMessage(CHAT_BOT_REVIEW_DUPLICATED.getMessage()); - } - - @DisplayName("사용자 질의 요약이 비어있다면 리뷰를 저장할 수 없다.") - @Test - void throwExceptionWhenSummaryIsEmtpy() { - // given - CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( - 1, - "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", - Map.of( - "recommandPlans", - List.of( - Map.of("aPlan", "5G 무제한"), - Map.of("bPlan", "내맘대로 5G 요금제") - ) - ), - 1L, - "684d9a790eea0b57af47a8d1" - ); - - given(restTemplate.postForObject( - anyString(), - any(CreateUserQuerySummaryRequest.class), - eq(QuestionSummaryDto.class) - )).willReturn(null); - - // when // then - assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) - .isInstanceOf(RestApiException.class) - .hasMessage(LLM_SUMMARY_FAIL.getMessage()); - } -} +// package com.ureca.ufit.chatbot.service; +// +// import static com.ureca.ufit.domain.chatbot.exception.ChatBotErrorCode.*; +// import static java.lang.Boolean.*; +// import static org.assertj.core.api.Assertions.*; +// import static org.junit.jupiter.api.Assertions.*; +// import static org.mockito.BDDMockito.*; +// +// import java.util.List; +// import java.util.Map; +// +// import org.junit.jupiter.api.DisplayName; +// import org.junit.jupiter.api.Test; +// import org.junit.jupiter.api.extension.ExtendWith; +// import org.mockito.InjectMocks; +// import org.mockito.Mock; +// import org.mockito.junit.jupiter.MockitoExtension; +// import org.springframework.web.client.RestTemplate; +// +// import com.ureca.ufit.common.fixture.ChatBotReviewFixture; +// import com.ureca.ufit.domain.chatbot.client.ChatClient; +// import com.ureca.ufit.domain.chatbot.dto.request.CreateChatBotReviewRequest; +// import com.ureca.ufit.domain.chatbot.dto.request.CreateUserQuerySummaryRequest; +// import com.ureca.ufit.domain.chatbot.dto.response.CreateChatBotReviewResponse; +// import com.ureca.ufit.domain.chatbot.dto.response.QuestionSummaryDto; +// import com.ureca.ufit.domain.chatbot.repository.ChatBotReviewRepository; +// import com.ureca.ufit.domain.chatbot.service.ChatBotMessageService; +// import com.ureca.ufit.domain.chatbot.service.ChatBotReviewService; +// import com.ureca.ufit.domain.chatbot.service.ChatRoomService; +// import com.ureca.ufit.entity.ChatBotReview; +// import com.ureca.ufit.global.exception.RestApiException; +// import com.ureca.ufit.global.profanity.ProfanityService; +// +// @ExtendWith(MockitoExtension.class) +// class ChatBotReviewServiceTest { +// +// @Mock +// // RestTemplate restTemplate; +// ChatClient chatClient; +// @Mock +// ChatBotReviewRepository chatBotReviewRepository; +// @Mock +// ProfanityService profanityService; +// @Mock +// ChatRoomService chatRoomService; +// @Mock +// ChatBotMessageService chatBotMessageService; +// @InjectMocks +// ChatBotReviewService chatBotReviewService; +// +// @DisplayName("챗봇 리뷰를 저장한다.") +// @Test +// void savedChatBotReview() { +// // given +// final String CHAT_REVIEW_SUCCESS_MSG = "리뷰가 정상적으로 제출되었습니다."; +// +// CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( +// 1, +// "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", +// Map.of( +// "recommandPlans", +// List.of( +// Map.of("aPlan", "5G 무제한"), +// Map.of("bPlan", "내맘대로 5G 요금제") +// ) +// ), +// 1L, +// "684d9a790eea0b57af47a8d1" +// ); +// QuestionSummaryDto questionSummaryDto = new QuestionSummaryDto("데이터 많은 요금제 추천해줘"); +// ChatBotReview chatBotReview = ChatBotReviewFixture.chatBotReview( +// request.content(), +// questionSummaryDto.summary() +// ); +// +// given(chatClient.getSummary(any(), anyLong())).willReturn(questionSummaryDto); +// +// // given(restTemplate.postForObject( +// // anyString(), +// // any(CreateUserQuerySummaryRequest.class), +// // eq(QuestionSummaryDto.class) +// // )).willReturn(questionSummaryDto); +// given(chatBotReviewRepository.save(any(ChatBotReview.class))).willReturn(chatBotReview); +// +// // when +// CreateChatBotReviewResponse response = chatBotReviewService.createChatBotReview(request); +// +// // then +// // assertAll( +// // () -> assertThat(response.message()).isEqualTo(CHAT_REVIEW_SUCCESS_MSG), +// // () -> verify(chatBotReviewRepository).save(any(ChatBotReview.class)), +// // () -> verify(restTemplate).postForObject( +// // anyString(), +// // any(CreateUserQuerySummaryRequest.class), +// // eq(QuestionSummaryDto.class)) +// // ); +// assertThat(response.message()).isEqualTo(CHAT_REVIEW_SUCCESS_MSG); +// verify(chatClient).getSummary(any(), anyLong()); +// verify(chatBotReviewRepository).save(any()); +// } +// +// @DisplayName("채팅방ID가 유효하지 않은 리뷰는 저장할 수 없다.") +// @Test +// void throwExceptionWhenChatRoomIdIsInvalid() { +// // given +// CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( +// 1, +// "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", +// Map.of( +// "recommandPlans", +// List.of( +// Map.of("aPlan", "5G 무제한"), +// Map.of("bPlan", "내맘대로 5G 요금제") +// ) +// ), +// 1L, +// "684d9a790eea0b57af47a8d1" +// ); +// +// doThrow(new RestApiException(CHATROOM_NOT_FOUND)) +// .when(chatRoomService) +// .getValidatedChatRoom(anyLong()); +// +// // when // then +// assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) +// .isInstanceOf(RestApiException.class) +// .hasMessage(CHATROOM_NOT_FOUND.getMessage()); +// } +// +// @DisplayName("리뷰 메시지와 채팅방이 일치하지 않으면 리뷰를 저장할 수 없다.") +// @Test +// void throwExceptionWhenChatBotMessageNotMatchChatRoom() { +// // given +// CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( +// 1, +// "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", +// Map.of( +// "recommandPlans", +// List.of( +// Map.of("aPlan", "5G 무제한"), +// Map.of("bPlan", "내맘대로 5G 요금제") +// ) +// ), +// 1L, +// "684d9a790eea0b57af47a8d1" +// ); +// +// doThrow(new RestApiException(INVALID_CHATBOT_MESSAGE)) +// .when(chatBotMessageService) +// .validateMessageBelongsToChatRoom(anyString(), anyLong()); +// +// // when // then +// assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) +// .isInstanceOf(RestApiException.class) +// .hasMessage(INVALID_CHATBOT_MESSAGE.getMessage()); +// } +// +// @DisplayName("챗봇 리뷰 내용에 금칙어가 포함되어 있으면 저장할 수 없다.") +// @Test +// void throwExceptionWhenChatBotReviewContentIsProfanity() { +// // given +// CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( +// 1, +// "추천 퀄리티가 존나 좋네요 ㅋㅋ", +// Map.of( +// "recommandPlans", +// List.of( +// Map.of("aPlan", "5G 무제한"), +// Map.of("bPlan", "내맘대로 5G 요금제") +// ) +// ), +// 1L, +// "684d9a790eea0b57af47a8d1" +// ); +// +// given(chatBotReviewRepository.existsByChatBotMessageId(anyString())).willReturn(FALSE); +// given(profanityService.containsBannedWord(anyString(), anySet())).willReturn(TRUE); +// +// // when // then +// assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) +// .isInstanceOf(RestApiException.class) +// .hasMessage(CONTENT_RESTRICTED_WORD.getMessage()); +// } +// +// @DisplayName("챗봇 리뷰를 중복해서 저장할 수 없다.") +// @Test +// void throwExceptionWhenChatBotReviewIsDuplicated() { +// // given +// CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( +// 1, +// "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", +// Map.of( +// "recommandPlans", +// List.of( +// Map.of("aPlan", "5G 무제한"), +// Map.of("bPlan", "내맘대로 5G 요금제") +// ) +// ), +// 1L, +// "684d9a790eea0b57af47a8d1" +// ); +// +// given(chatBotReviewRepository.existsByChatBotMessageId(anyString())).willReturn(TRUE); +// +// // when // then +// assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) +// .isInstanceOf(RestApiException.class) +// .hasMessage(CHAT_BOT_REVIEW_DUPLICATED.getMessage()); +// } +// // +// // @DisplayName("사용자 질의 요약이 비어있다면 리뷰를 저장할 수 없다.") +// // @Test +// // void throwExceptionWhenSummaryIsEmtpy() { +// // // given +// // CreateChatBotReviewRequest request = new CreateChatBotReviewRequest( +// // 1, +// // "추천 퀄리티가 너무 좋아서 깜짝 놀랐어요.", +// // Map.of( +// // "recommandPlans", +// // List.of( +// // Map.of("aPlan", "5G 무제한"), +// // Map.of("bPlan", "내맘대로 5G 요금제") +// // ) +// // ), +// // 1L, +// // "684d9a790eea0b57af47a8d1" +// // ); +// // +// // // given(restTemplate.postForObject( +// // // anyString(), +// // // any(CreateUserQuerySummaryRequest.class), +// // // eq(QuestionSummaryDto.class) +// // // )).willReturn(null); +// // given(chatClient.getSummary(any(), anyLong())).willReturn(null); +// // +// // +// // // when // then +// // assertThatThrownBy(() -> chatBotReviewService.createChatBotReview(request)) +// // .isInstanceOf(RestApiException.class) +// // .hasMessage(LLM_SUMMARY_FAIL.getMessage()); +// // } +// }