Skip to content

Commit 5110bbf

Browse files
committed
Merge remote-tracking branch 'origin/develop' into develop
2 parents 44c0ac3 + 1e9068a commit 5110bbf

2 files changed

Lines changed: 273 additions & 1 deletion

File tree

src/main/java/com/swunitzel/fiterview/services/ReportService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import org.springframework.stereotype.Service;
1818
import org.springframework.transaction.annotation.Transactional;
1919

20+
import java.util.Collections;
2021
import java.util.List;
22+
import java.util.Optional;
2123
import java.util.stream.Collectors;
2224

2325
@Service
@@ -82,7 +84,7 @@ public ReportDto.NonverbalCommunicationReportDto getNonverbalCommunicationReport
8284
float avgTurnRightCount = totalTurnRightCount / answerCount;
8385

8486
List<List<GazePoint>> gazePointsList = answers.stream()
85-
.map(Answer::getGazePoints)
87+
.map(answer -> Optional.ofNullable(answer.getGazePoints()).orElse(Collections.emptyList()))
8688
.collect(Collectors.toList());
8789

8890
// 인터뷰에 총첨 업데이트
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
package com.swunitzel.fiterview.services;
2+
3+
import com.swunitzel.fiterview.apiPayload.exception.handler.AnswerHandler;
4+
import com.swunitzel.fiterview.apiPayload.exception.handler.CombineHandler;
5+
import com.swunitzel.fiterview.apiPayload.exception.handler.InterviewHandler;
6+
import com.swunitzel.fiterview.converter.ReportConverter;
7+
import com.swunitzel.fiterview.domain.Answer;
8+
import com.swunitzel.fiterview.domain.Combine;
9+
import com.swunitzel.fiterview.domain.GazePoint;
10+
import com.swunitzel.fiterview.domain.Interview;
11+
import com.swunitzel.fiterview.dto.ReportDto;
12+
import com.swunitzel.fiterview.repository.AnswerRepository;
13+
import com.swunitzel.fiterview.repository.CombineRepository;
14+
import com.swunitzel.fiterview.repository.InterviewRepository;
15+
import org.junit.jupiter.api.DisplayName;
16+
import org.junit.jupiter.api.Test;
17+
import org.junit.jupiter.api.extension.ExtendWith;
18+
import org.mockito.ArgumentCaptor;
19+
import org.mockito.InjectMocks;
20+
import org.mockito.Mock;
21+
import org.mockito.MockedStatic;
22+
import org.mockito.junit.jupiter.MockitoExtension;
23+
24+
import java.time.LocalDateTime;
25+
import java.util.Arrays;
26+
import java.util.List;
27+
import java.util.Optional;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
31+
import static org.mockito.ArgumentMatchers.anyFloat;
32+
import static org.mockito.ArgumentMatchers.anyList;
33+
import static org.mockito.Mockito.*;
34+
35+
@ExtendWith(MockitoExtension.class)
36+
class ReportServiceTest {
37+
38+
@Mock
39+
private AnswerRepository answerRepository;
40+
41+
@Mock
42+
private InterviewRepository interviewRepository;
43+
44+
@Mock
45+
private CombineRepository combineRepository;
46+
47+
@InjectMocks
48+
private ReportService reportService;
49+
50+
@Test
51+
@DisplayName("정상적인 비언어적 커뮤니케이션 리포트 생성 테스트")
52+
void getNonverbalCommunicationReport_Success() {
53+
// Given
54+
String interviewId = "test-interview-id";
55+
String combineId = "test-combine-id";
56+
57+
// Mock Answer 데이터 생성
58+
Answer answer1 = createMockAnswer(5, 3, 2, 0.8f, 10, 15.0f);
59+
Answer answer2 = createMockAnswer(3, 4, 1, 0.6f, 8, 12.0f);
60+
List<Answer> answers = Arrays.asList(answer1, answer2);
61+
62+
// Mock Interview 데이터 생성
63+
Interview interview = createMockInterview(interviewId, combineId);
64+
Interview updatedInterview = createMockUpdatedInterview();
65+
66+
// Mock Combine 데이터 생성
67+
Combine combine = createMockCombine(combineId);
68+
69+
// Mock ReportDto 생성
70+
ReportDto.NonverbalCommunicationReportDto expectedDto = createMockReportDto();
71+
72+
// When
73+
when(answerRepository.findAllByInterviewId(interviewId)).thenReturn(answers);
74+
when(interviewRepository.findById(interviewId)).thenReturn(Optional.of(interview));
75+
when(interview.updateNonverbalCommunicationReport(anyFloat(), anyFloat(), anyFloat(),
76+
anyFloat(), anyFloat(), anyFloat(), anyList())).thenReturn(updatedInterview);
77+
when(combineRepository.findById(combineId)).thenReturn(Optional.of(combine));
78+
try (MockedStatic<ReportConverter> mocked = mockStatic(ReportConverter.class)) {
79+
mocked.when(() -> ReportConverter.toNonverbalCommunicationReportDto(updatedInterview, combine))
80+
.thenReturn(expectedDto);
81+
82+
// When
83+
ReportDto.NonverbalCommunicationReportDto result =
84+
reportService.getNonverbalCommunicationReport(interviewId);
85+
86+
// Then
87+
assertThat(result).isNotNull();
88+
assertThat(result).isEqualTo(expectedDto);
89+
}
90+
91+
// Verify 메서드 호출 검증
92+
verify(answerRepository).findAllByInterviewId(interviewId);
93+
verify(interviewRepository).findById(interviewId);
94+
verify(combineRepository).findById(combineId);
95+
verify(interview).updateNonverbalCommunicationReport(anyFloat(), anyFloat(), anyFloat(),
96+
anyFloat(), anyFloat(), anyFloat(), anyList());
97+
}
98+
99+
@Test
100+
@DisplayName("Answer가 없을 경우 예외 발생 테스트")
101+
void getNonverbalCommunicationReport_AnswerNotFound() {
102+
// Given
103+
String interviewId = "test-interview-id";
104+
105+
// When
106+
when(answerRepository.findAllByInterviewId(interviewId)).thenReturn(null);
107+
108+
// Then
109+
assertThatThrownBy(() -> reportService.getNonverbalCommunicationReport(interviewId))
110+
.isInstanceOf(AnswerHandler.class);
111+
112+
verify(answerRepository).findAllByInterviewId(interviewId);
113+
}
114+
115+
@Test
116+
@DisplayName("Answer 필드가 null인 경우 예외 발생 테스트")
117+
void getNonverbalCommunicationReport_AnswerFieldIsNull() {
118+
// Given
119+
String interviewId = "test-interview-id";
120+
Answer answerWithNullFields = createMockAnswerWithNullFields();
121+
List<Answer> answers = Arrays.asList(answerWithNullFields);
122+
123+
// When
124+
when(answerRepository.findAllByInterviewId(interviewId)).thenReturn(answers);
125+
126+
// Then
127+
assertThatThrownBy(() -> reportService.getNonverbalCommunicationReport(interviewId))
128+
.isInstanceOf(AnswerHandler.class);
129+
130+
verify(answerRepository).findAllByInterviewId(interviewId);
131+
}
132+
133+
@Test
134+
@DisplayName("Interview가 없을 경우 예외 발생 테스트")
135+
void getNonverbalCommunicationReport_InterviewNotFound() {
136+
// Given
137+
String interviewId = "test-interview-id";
138+
Answer answer = createMockAnswer(5, 3, 2, 0.8f, 10, 15.0f);
139+
List<Answer> answers = Arrays.asList(answer);
140+
141+
// When
142+
when(answerRepository.findAllByInterviewId(interviewId)).thenReturn(answers);
143+
when(interviewRepository.findById(interviewId)).thenReturn(Optional.empty());
144+
145+
// Then
146+
assertThatThrownBy(() -> reportService.getNonverbalCommunicationReport(interviewId))
147+
.isInstanceOf(InterviewHandler.class);
148+
149+
verify(answerRepository).findAllByInterviewId(interviewId);
150+
verify(interviewRepository).findById(interviewId);
151+
}
152+
153+
@Test
154+
@DisplayName("Combine이 없을 경우 예외 발생 테스트")
155+
void getNonverbalCommunicationReport_CombineNotFound() {
156+
// Given
157+
String interviewId = "test-interview-id";
158+
String combineId = "test-combine-id";
159+
Answer answer = createMockAnswer(5, 3, 2, 0.8f, 10, 15.0f);
160+
List<Answer> answers = Arrays.asList(answer);
161+
Interview interview = createMockInterview(interviewId, combineId);
162+
Interview updatedInterview = createMockUpdatedInterview();
163+
164+
// When
165+
when(answerRepository.findAllByInterviewId(interviewId)).thenReturn(answers);
166+
when(interviewRepository.findById(interviewId)).thenReturn(Optional.of(interview));
167+
when(interview.updateNonverbalCommunicationReport(anyFloat(), anyFloat(), anyFloat(),
168+
anyFloat(), anyFloat(), anyFloat(), anyList())).thenReturn(updatedInterview);
169+
when(combineRepository.findById(combineId)).thenReturn(Optional.empty());
170+
171+
// Then
172+
assertThatThrownBy(() -> reportService.getNonverbalCommunicationReport(interviewId))
173+
.isInstanceOf(CombineHandler.class);
174+
175+
verify(answerRepository).findAllByInterviewId(interviewId);
176+
verify(interviewRepository).findById(interviewId);
177+
verify(combineRepository).findById(combineId);
178+
}
179+
180+
@Test
181+
@DisplayName("GazePoints가 null인 경우 빈 리스트로 처리되는지 테스트")
182+
void getNonverbalCommunicationReport_GazePointsNull() {
183+
// Given
184+
String interviewId = "test-interview-id";
185+
String combineId = "test-combine-id";
186+
187+
Answer answer = createMockAnswer(5, 3, 2, 0.8f, 10, 15.0f);
188+
when(answer.getGazePoints()).thenReturn(null); // GazePoints를 null로 설정
189+
List<Answer> answers = Arrays.asList(answer);
190+
191+
Interview interview = createMockInterview(interviewId, combineId);
192+
Interview updatedInterview = createMockUpdatedInterview();
193+
Combine combine = createMockCombine(combineId);
194+
ReportDto.NonverbalCommunicationReportDto expectedDto = createMockReportDto();
195+
196+
// When
197+
when(answerRepository.findAllByInterviewId(interviewId)).thenReturn(answers);
198+
when(interviewRepository.findById(interviewId)).thenReturn(Optional.of(interview));
199+
when(interview.updateNonverbalCommunicationReport(anyFloat(), anyFloat(), anyFloat(),
200+
anyFloat(), anyFloat(), anyFloat(), anyList())).thenReturn(updatedInterview);
201+
when(combineRepository.findById(combineId)).thenReturn(Optional.of(combine));
202+
try (MockedStatic<ReportConverter> mocked = mockStatic(ReportConverter.class)) {
203+
mocked.when(() -> ReportConverter.toNonverbalCommunicationReportDto(updatedInterview, combine))
204+
.thenReturn(expectedDto);
205+
206+
// When
207+
ReportDto.NonverbalCommunicationReportDto result =
208+
reportService.getNonverbalCommunicationReport(interviewId);
209+
210+
// Then
211+
assertThat(result).isNotNull();
212+
}
213+
214+
// gazePointsList에 빈 리스트가 포함되어야 함
215+
ArgumentCaptor<List<List<GazePoint>>> gazePointsCaptor =
216+
ArgumentCaptor.forClass(List.class);
217+
verify(interview).updateNonverbalCommunicationReport(anyFloat(), anyFloat(), anyFloat(),
218+
anyFloat(), anyFloat(), anyFloat(), gazePointsCaptor.capture());
219+
220+
List<List<GazePoint>> capturedGazePoints = gazePointsCaptor.getValue();
221+
assertThat(capturedGazePoints).hasSize(1);
222+
assertThat(capturedGazePoints.get(0)).isEmpty();
223+
}
224+
225+
// Helper methods
226+
private Answer createMockAnswer(int shoulderTilt, int turnLeft, int turnRight,
227+
float smileRatio, int gazeDown, float blinksPerMinute) {
228+
Answer answer = mock(Answer.class);
229+
when(answer.getShoulderTiltCount()).thenReturn(shoulderTilt);
230+
when(answer.getTurnLeftCount()).thenReturn(turnLeft);
231+
when(answer.getTurnRightCount()).thenReturn(turnRight);
232+
when(answer.getSmileRatio()).thenReturn(smileRatio);
233+
when(answer.getGazeDownCount()).thenReturn(gazeDown);
234+
when(answer.getBlinksPerMinute()).thenReturn(blinksPerMinute);
235+
when(answer.getGazePoints()).thenReturn(Arrays.asList(
236+
createRealGazePoint(5, 3),
237+
createRealGazePoint(7, 4)
238+
));
239+
return answer;
240+
}
241+
242+
private Answer createMockAnswerWithNullFields() {
243+
Answer answer = mock(Answer.class);
244+
when(answer.getShoulderTiltCount()).thenReturn(null); // null 필드
245+
return answer;
246+
}
247+
248+
private GazePoint createRealGazePoint(int x, int y) {
249+
return new GazePoint(x, y, LocalDateTime.now());
250+
}
251+
252+
private Interview createMockInterview(String interviewId, String combineId) {
253+
Interview interview = mock(Interview.class);
254+
when(interview.getCombineId()).thenReturn(combineId);
255+
return interview;
256+
}
257+
258+
private Interview createMockUpdatedInterview() {
259+
return mock(Interview.class);
260+
}
261+
262+
private Combine createMockCombine(String combineId) {
263+
Combine combine = mock(Combine.class);
264+
return combine;
265+
}
266+
267+
private ReportDto.NonverbalCommunicationReportDto createMockReportDto() {
268+
return mock(ReportDto.NonverbalCommunicationReportDto.class);
269+
}
270+
}

0 commit comments

Comments
 (0)