Skip to content

Commit 980f08c

Browse files
authored
Revert "chore : AI 피드백 길이 검증 부분 주석 처리 (#359)" (#360)
This reverts commit b26cd78.
1 parent b26cd78 commit 980f08c

File tree

5 files changed

+1104
-1105
lines changed

5 files changed

+1104
-1105
lines changed

cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import com.example.cs25entity.domain.user.repository.UserRepository;
55
import com.example.cs25entity.domain.userQuizAnswer.repository.UserQuizAnswerRepository;
66
import com.example.cs25service.domain.ai.client.AiChatClient;
7-
//import com.example.cs25service.domain.ai.exception.AiException;
8-
//import com.example.cs25service.domain.ai.exception.AiExceptionCode;
7+
import com.example.cs25service.domain.ai.exception.AiException;
8+
import com.example.cs25service.domain.ai.exception.AiExceptionCode;
99
import com.example.cs25service.domain.ai.prompt.AiPromptProvider;
1010
import com.fasterxml.jackson.databind.JsonNode;
1111
import java.io.IOException;
@@ -91,10 +91,9 @@ public void stream(Long answerId, SseEmitter emitter) {
9191
send(emitter, "[종료]");
9292

9393
String feedback = fullFeedbackBuffer.toString();
94-
//서비스 흐름 상 예외를 던지는 유효성 검증이 옳은지 논의 필요
95-
// if (feedback == null || feedback.isEmpty()) {
96-
// throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR);
97-
// }
94+
if (feedback == null || feedback.isEmpty()) {
95+
throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR);
96+
}
9897

9998
boolean isCorrect = isCorrect(feedback);
10099

Lines changed: 170 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,170 +1,170 @@
1-
//package com.example.cs25service.ai;
2-
//
3-
//import static org.assertj.core.api.Assertions.assertThat;
4-
//
5-
//import com.example.cs25entity.domain.quiz.entity.Quiz;
6-
//import com.example.cs25entity.domain.quiz.entity.QuizCategory;
7-
//import com.example.cs25entity.domain.quiz.enums.QuizFormatType;
8-
//import com.example.cs25entity.domain.quiz.enums.QuizLevel;
9-
//import com.example.cs25entity.domain.quiz.repository.QuizRepository;
10-
//import com.example.cs25entity.domain.subscription.entity.Subscription;
11-
//import com.example.cs25entity.domain.subscription.repository.SubscriptionRepository;
12-
//import com.example.cs25entity.domain.user.repository.UserRepository;
13-
//import com.example.cs25entity.domain.userQuizAnswer.entity.UserQuizAnswer;
14-
//import com.example.cs25entity.domain.userQuizAnswer.repository.UserQuizAnswerRepository;
15-
//import com.example.cs25service.domain.ai.client.AiChatClient;
16-
//import com.example.cs25service.domain.ai.dto.response.AiFeedbackResponse;
17-
//import com.example.cs25service.domain.ai.prompt.AiPromptProvider;
18-
//import com.example.cs25service.domain.ai.service.AiFeedbackQueueService;
19-
//import com.example.cs25service.domain.ai.service.AiFeedbackStreamWorker;
20-
//import com.example.cs25service.domain.ai.service.AiService;
21-
//import com.example.cs25service.domain.ai.service.RagService;
22-
//import jakarta.persistence.EntityManager;
23-
//import jakarta.persistence.PersistenceContext;
24-
//import java.time.LocalDate;
25-
//
26-
//import org.junit.jupiter.api.*;
27-
//import org.springframework.ai.chat.client.ChatClient;
28-
//import org.springframework.beans.factory.annotation.Autowired;
29-
//import org.springframework.boot.test.context.SpringBootTest;
30-
//import org.springframework.test.annotation.DirtiesContext;
31-
//import org.springframework.transaction.annotation.Transactional;
32-
//import static org.mockito.Mockito.mock;
33-
//
34-
//@SpringBootTest
35-
//@Transactional
36-
//@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) // 스프링 컨텍스트 리프레시
37-
//@Disabled
38-
//public class AiServiceTest {
39-
// @Autowired
40-
// private AiService aiService;
41-
//
42-
// @Autowired
43-
// private QuizRepository quizRepository;
44-
//
45-
// @Autowired
46-
// private UserQuizAnswerRepository userQuizAnswerRepository;
47-
//
48-
// @Autowired
49-
// private SubscriptionRepository subscriptionRepository;
50-
//
51-
// @Autowired
52-
// private AiFeedbackStreamWorker aiFeedbackStreamWorker;
53-
//
54-
// @PersistenceContext
55-
// private EntityManager em;
56-
//
57-
// private Quiz quiz;
58-
// private Subscription memberSubscription;
59-
// private Subscription guestSubscription;
60-
// private UserQuizAnswer answerWithMember;
61-
// private UserQuizAnswer answerWithGuest;
62-
//
63-
// @BeforeEach
64-
// void setUp() {
65-
// // 카테고리 생성
66-
// QuizCategory quizCategory = new QuizCategory("BACKEND", null);
67-
// em.persist(quizCategory);
68-
//
69-
// // 퀴즈 생성
70-
// quiz = Quiz.builder()
71-
// .type(QuizFormatType.SUBJECTIVE)
72-
// .question("HTTP와 HTTPS의 차이점을 설명하세요.")
73-
// .answer("HTTPS는 암호화, HTTP는 암호화X")
74-
// .commentary("HTTPS는 SSL/TLS로 암호화되어 보안성이 높다.")
75-
// .choice(null)
76-
// .category(quizCategory)
77-
// .level(QuizLevel.EASY)
78-
// .build();
79-
// quizRepository.save(quiz);
80-
//
81-
// // 구독 생성 (회원, 비회원)
82-
// memberSubscription = Subscription.builder()
83-
// .email("test@example.com")
84-
// .startDate(LocalDate.now())
85-
// .endDate(LocalDate.now().plusDays(30))
86-
// .subscriptionType(Subscription.decodeDays(0b1111111))
87-
// .build();
88-
// subscriptionRepository.save(memberSubscription);
89-
//
90-
// guestSubscription = Subscription.builder()
91-
// .email("guest@example.com")
92-
// .startDate(LocalDate.now())
93-
// .endDate(LocalDate.now().plusDays(7))
94-
// .subscriptionType(Subscription.decodeDays(0b1111111))
95-
// .build();
96-
// subscriptionRepository.save(guestSubscription);
97-
//
98-
// // 사용자 답변 생성
99-
// answerWithMember = UserQuizAnswer.builder()
100-
// .userAnswer("HTTP는 암호화가 없고, HTTPS는 암호화로 보안성이 높아요.")
101-
// .subscription(memberSubscription)
102-
// .isCorrect(null)
103-
// .quiz(quiz)
104-
// .build();
105-
// userQuizAnswerRepository.save(answerWithMember);
106-
//
107-
// answerWithGuest = UserQuizAnswer.builder()
108-
// .userAnswer("HTTP는 암호화가 없고, HTTPS는 암호화로 보안성이 높아요.")
109-
// .subscription(guestSubscription)
110-
// .isCorrect(null)
111-
// .quiz(quiz)
112-
// .build();
113-
// userQuizAnswerRepository.save(answerWithGuest);
114-
//
115-
// }
116-
//
117-
// @Test
118-
// void testGetFeedbackForMember() {
119-
// AiFeedbackResponse response = aiService.getFeedback(answerWithMember.getId());
120-
//
121-
// assertThat(response).isNotNull();
122-
// assertThat(response.getQuizId()).isEqualTo(quiz.getId());
123-
// assertThat(response.getQuizAnswerId()).isEqualTo(answerWithMember.getId());
124-
// assertThat(response.getAiFeedback()).isNotBlank();
125-
//
126-
// var updated = userQuizAnswerRepository.findById(answerWithMember.getId()).orElseThrow();
127-
// assertThat(updated.getAiFeedback()).isEqualTo(response.getAiFeedback());
128-
// assertThat(updated.getIsCorrect()).isNotNull();
129-
//
130-
// System.out.println("[회원 구독] AI 피드백:\n" + response.getAiFeedback());
131-
// }
132-
//
133-
// @Test
134-
// void testGetFeedbackForGuest() {
135-
// AiFeedbackResponse response = aiService.getFeedback(answerWithGuest.getId());
136-
//
137-
// assertThat(response).isNotNull();
138-
// assertThat(response.getQuizId()).isEqualTo(quiz.getId());
139-
// assertThat(response.getQuizAnswerId()).isEqualTo(answerWithGuest.getId());
140-
// assertThat(response.getAiFeedback()).isNotBlank();
141-
//
142-
// var updated = userQuizAnswerRepository.findById(answerWithGuest.getId()).orElseThrow();
143-
// assertThat(updated.getAiFeedback()).isEqualTo(response.getAiFeedback());
144-
// assertThat(updated.getIsCorrect()).isNotNull();
145-
//
146-
// System.out.println("[비회원 구독] AI 피드백:\n" + response.getAiFeedback());
147-
// }
148-
//
149-
// @Test
150-
// @DisplayName("6글자 이내에 정답이 포함된 경우 true 반환")
151-
// void testIfAiFeedbackIsCorrectThenReturnTrue(){
152-
// assertThat(aiService.isCorrect("- 정답 : 당신의 답은 완벽합니다.")).isTrue();
153-
// assertThat(aiService.isCorrect("정답 : 당신의 답은 완벽합니다.")).isTrue();
154-
// assertThat(aiService.isCorrect("정답입니다. 당신의 답은 완벽합니다.")).isTrue();
155-
// }
156-
//
157-
// @Test
158-
// @DisplayName("오답인 경우 false 반환")
159-
// void testIfAiFeedbackIsWrongThenReturnfalse(){
160-
// assertThat(aiService.isCorrect("- 오답 : 당신의 답은 완벽합니다.")).isFalse();
161-
// assertThat(aiService.isCorrect("오답 : 당신의 답은 완벽합니다.")).isFalse();
162-
// assertThat(aiService.isCorrect("오답입니다. 당신의 답은 완벽합니다.")).isFalse();
163-
// assertThat(aiService.isCorrect("오답: 정답이라고 하기에는 부족합니다.")).isFalse();
164-
// }
165-
//
166-
// @AfterEach
167-
// void tearDown() {
168-
// aiFeedbackStreamWorker.stop();
169-
// }
170-
//}
1+
package com.example.cs25service.ai;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import com.example.cs25entity.domain.quiz.entity.Quiz;
6+
import com.example.cs25entity.domain.quiz.entity.QuizCategory;
7+
import com.example.cs25entity.domain.quiz.enums.QuizFormatType;
8+
import com.example.cs25entity.domain.quiz.enums.QuizLevel;
9+
import com.example.cs25entity.domain.quiz.repository.QuizRepository;
10+
import com.example.cs25entity.domain.subscription.entity.Subscription;
11+
import com.example.cs25entity.domain.subscription.repository.SubscriptionRepository;
12+
import com.example.cs25entity.domain.user.repository.UserRepository;
13+
import com.example.cs25entity.domain.userQuizAnswer.entity.UserQuizAnswer;
14+
import com.example.cs25entity.domain.userQuizAnswer.repository.UserQuizAnswerRepository;
15+
import com.example.cs25service.domain.ai.client.AiChatClient;
16+
import com.example.cs25service.domain.ai.dto.response.AiFeedbackResponse;
17+
import com.example.cs25service.domain.ai.prompt.AiPromptProvider;
18+
import com.example.cs25service.domain.ai.service.AiFeedbackQueueService;
19+
import com.example.cs25service.domain.ai.service.AiFeedbackStreamWorker;
20+
import com.example.cs25service.domain.ai.service.AiService;
21+
import com.example.cs25service.domain.ai.service.RagService;
22+
import jakarta.persistence.EntityManager;
23+
import jakarta.persistence.PersistenceContext;
24+
import java.time.LocalDate;
25+
26+
import org.junit.jupiter.api.*;
27+
import org.springframework.ai.chat.client.ChatClient;
28+
import org.springframework.beans.factory.annotation.Autowired;
29+
import org.springframework.boot.test.context.SpringBootTest;
30+
import org.springframework.test.annotation.DirtiesContext;
31+
import org.springframework.transaction.annotation.Transactional;
32+
import static org.mockito.Mockito.mock;
33+
34+
@SpringBootTest
35+
@Transactional
36+
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) // 스프링 컨텍스트 리프레시
37+
@Disabled
38+
public class AiServiceTest {
39+
@Autowired
40+
private AiService aiService;
41+
42+
@Autowired
43+
private QuizRepository quizRepository;
44+
45+
@Autowired
46+
private UserQuizAnswerRepository userQuizAnswerRepository;
47+
48+
@Autowired
49+
private SubscriptionRepository subscriptionRepository;
50+
51+
@Autowired
52+
private AiFeedbackStreamWorker aiFeedbackStreamWorker;
53+
54+
@PersistenceContext
55+
private EntityManager em;
56+
57+
private Quiz quiz;
58+
private Subscription memberSubscription;
59+
private Subscription guestSubscription;
60+
private UserQuizAnswer answerWithMember;
61+
private UserQuizAnswer answerWithGuest;
62+
63+
@BeforeEach
64+
void setUp() {
65+
// 카테고리 생성
66+
QuizCategory quizCategory = new QuizCategory("BACKEND", null);
67+
em.persist(quizCategory);
68+
69+
// 퀴즈 생성
70+
quiz = Quiz.builder()
71+
.type(QuizFormatType.SUBJECTIVE)
72+
.question("HTTP와 HTTPS의 차이점을 설명하세요.")
73+
.answer("HTTPS는 암호화, HTTP는 암호화X")
74+
.commentary("HTTPS는 SSL/TLS로 암호화되어 보안성이 높다.")
75+
.choice(null)
76+
.category(quizCategory)
77+
.level(QuizLevel.EASY)
78+
.build();
79+
quizRepository.save(quiz);
80+
81+
// 구독 생성 (회원, 비회원)
82+
memberSubscription = Subscription.builder()
83+
.email("test@example.com")
84+
.startDate(LocalDate.now())
85+
.endDate(LocalDate.now().plusDays(30))
86+
.subscriptionType(Subscription.decodeDays(0b1111111))
87+
.build();
88+
subscriptionRepository.save(memberSubscription);
89+
90+
guestSubscription = Subscription.builder()
91+
.email("guest@example.com")
92+
.startDate(LocalDate.now())
93+
.endDate(LocalDate.now().plusDays(7))
94+
.subscriptionType(Subscription.decodeDays(0b1111111))
95+
.build();
96+
subscriptionRepository.save(guestSubscription);
97+
98+
// 사용자 답변 생성
99+
answerWithMember = UserQuizAnswer.builder()
100+
.userAnswer("HTTP는 암호화가 없고, HTTPS는 암호화로 보안성이 높아요.")
101+
.subscription(memberSubscription)
102+
.isCorrect(null)
103+
.quiz(quiz)
104+
.build();
105+
userQuizAnswerRepository.save(answerWithMember);
106+
107+
answerWithGuest = UserQuizAnswer.builder()
108+
.userAnswer("HTTP는 암호화가 없고, HTTPS는 암호화로 보안성이 높아요.")
109+
.subscription(guestSubscription)
110+
.isCorrect(null)
111+
.quiz(quiz)
112+
.build();
113+
userQuizAnswerRepository.save(answerWithGuest);
114+
115+
}
116+
117+
@Test
118+
void testGetFeedbackForMember() {
119+
AiFeedbackResponse response = aiService.getFeedback(answerWithMember.getId());
120+
121+
assertThat(response).isNotNull();
122+
assertThat(response.getQuizId()).isEqualTo(quiz.getId());
123+
assertThat(response.getQuizAnswerId()).isEqualTo(answerWithMember.getId());
124+
assertThat(response.getAiFeedback()).isNotBlank();
125+
126+
var updated = userQuizAnswerRepository.findById(answerWithMember.getId()).orElseThrow();
127+
assertThat(updated.getAiFeedback()).isEqualTo(response.getAiFeedback());
128+
assertThat(updated.getIsCorrect()).isNotNull();
129+
130+
System.out.println("[회원 구독] AI 피드백:\n" + response.getAiFeedback());
131+
}
132+
133+
@Test
134+
void testGetFeedbackForGuest() {
135+
AiFeedbackResponse response = aiService.getFeedback(answerWithGuest.getId());
136+
137+
assertThat(response).isNotNull();
138+
assertThat(response.getQuizId()).isEqualTo(quiz.getId());
139+
assertThat(response.getQuizAnswerId()).isEqualTo(answerWithGuest.getId());
140+
assertThat(response.getAiFeedback()).isNotBlank();
141+
142+
var updated = userQuizAnswerRepository.findById(answerWithGuest.getId()).orElseThrow();
143+
assertThat(updated.getAiFeedback()).isEqualTo(response.getAiFeedback());
144+
assertThat(updated.getIsCorrect()).isNotNull();
145+
146+
System.out.println("[비회원 구독] AI 피드백:\n" + response.getAiFeedback());
147+
}
148+
149+
@Test
150+
@DisplayName("6글자 이내에 정답이 포함된 경우 true 반환")
151+
void testIfAiFeedbackIsCorrectThenReturnTrue(){
152+
assertThat(aiService.isCorrect("- 정답 : 당신의 답은 완벽합니다.")).isTrue();
153+
assertThat(aiService.isCorrect("정답 : 당신의 답은 완벽합니다.")).isTrue();
154+
assertThat(aiService.isCorrect("정답입니다. 당신의 답은 완벽합니다.")).isTrue();
155+
}
156+
157+
@Test
158+
@DisplayName("오답인 경우 false 반환")
159+
void testIfAiFeedbackIsWrongThenReturnfalse(){
160+
assertThat(aiService.isCorrect("- 오답 : 당신의 답은 완벽합니다.")).isFalse();
161+
assertThat(aiService.isCorrect("오답 : 당신의 답은 완벽합니다.")).isFalse();
162+
assertThat(aiService.isCorrect("오답입니다. 당신의 답은 완벽합니다.")).isFalse();
163+
assertThat(aiService.isCorrect("오답: 정답이라고 하기에는 부족합니다.")).isFalse();
164+
}
165+
166+
@AfterEach
167+
void tearDown() {
168+
aiFeedbackStreamWorker.stop();
169+
}
170+
}

0 commit comments

Comments
 (0)