Skip to content

Commit ab4f4ff

Browse files
authored
Merge pull request #74 from team-withiy/issue#73/test/event
test: event test code
2 parents 48b8588 + 6b71b22 commit ab4f4ff

File tree

3 files changed

+178
-15
lines changed

3 files changed

+178
-15
lines changed

src/main/java/com/server/domain/event/dto/CrawlingEventDto.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
@Getter
99
@Setter
1010
@NoArgsConstructor
11+
@AllArgsConstructor
1112
public class CrawlingEventDto {
1213
@JsonProperty("ranking")
1314
private int ranking;

src/main/resources/application-test.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ spring:
5353
token-uri: https://kauth.kakao.com/oauth/token
5454
user-info-uri: https://kapi.kakao.com/v2/user/me
5555
user-name-attribute: id
56+
hmac:
57+
secret-key: test_secret_key_7a8b9c0d1e2f3g4h5i6j7k8l9m0n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5c6d
5658
kakao:
5759
map:
5860
api:
59-
key: "kakao-map-key"
60-
hmac:
61-
secret-key: test_secret_key_7a8b9c0d1e2f3g4h5i6j7k8l9m0n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5c6d
61+
key: "kakao-map-key"

src/test/java/com/server/domain/event/controller/EventControllerTest.java

+174-12
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,72 @@
11
package com.server.domain.event.controller;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.server.domain.event.dto.CrawlingEventDto;
5+
import com.server.domain.event.dto.CrawlingEventDtoList;
36
import com.server.domain.event.dto.EventDto;
47
import com.server.domain.event.service.EventService;
58
import com.server.global.dto.ApiResponseDto;
9+
import com.server.global.etc.HmacUtil;
10+
import jakarta.servlet.http.HttpServletRequest;
11+
import lombok.RequiredArgsConstructor;
612
import org.junit.jupiter.api.BeforeEach;
713
import org.junit.jupiter.api.DisplayName;
814
import org.junit.jupiter.api.Test;
915
import org.junit.jupiter.api.extension.ExtendWith;
1016
import org.mockito.InjectMocks;
1117
import org.mockito.Mock;
1218
import org.mockito.junit.jupiter.MockitoExtension;
19+
import org.springframework.beans.factory.annotation.Value;
1320
import org.springframework.http.HttpStatus;
1421
import org.springframework.test.web.servlet.MockMvc;
1522
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
1623

24+
import java.lang.reflect.Field;
1725
import java.time.LocalDate;
26+
import java.time.format.DateTimeFormatter;
1827
import java.util.ArrayList;
28+
import java.util.Arrays;
1929
import java.util.List;
2030

2131
import static org.junit.jupiter.api.Assertions.assertEquals;
22-
import static org.mockito.Mockito.when;
32+
import static org.junit.jupiter.api.Assertions.assertThrows;
33+
import static org.mockito.ArgumentMatchers.any;
34+
import static org.mockito.Mockito.*;
2335
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
2436
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
2537
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
2638

39+
2740
@ExtendWith(MockitoExtension.class)
2841
public class EventControllerTest {
2942

3043
@Mock
3144
private EventService eventService;
3245

33-
@InjectMocks
3446
private EventController eventController;
3547

48+
private String SECRET_KEY;
49+
private ObjectMapper objectMapper;
50+
3651
private MockMvc mockMvc;
3752
private List<EventDto> sampleEvents;
3853

3954
@BeforeEach
4055
void setUp() {
56+
objectMapper = new ObjectMapper();
57+
SECRET_KEY = "test_secret_key_7a8b9c0d1e2f3g4h5i6j7k8l9m0n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5c6d";
58+
59+
60+
eventController = new EventController(eventService, objectMapper);
61+
62+
63+
// @Value("${hmac.secret-key}")를 수동으로 주입
64+
injectSecretKey(eventController, SECRET_KEY);
65+
4166
mockMvc = MockMvcBuilders.standaloneSetup(eventController).build();
4267

68+
69+
4370
sampleEvents = new ArrayList<>();
4471
sampleEvents.add(EventDto.builder().ranking(1).genre("콘서트").title("Sample Concert")
4572
.place("Seoul Arena").startDate(LocalDate.now())
@@ -68,20 +95,107 @@ void getEventsSuccessTest() {
6895
assertEquals(sampleEvents.get(1).getGenre(), response.getData().get(1).getGenre());
6996
}
7097

71-
/*@Test
72-
@DisplayName("이벤트 저장하기 성공 테스트")
73-
void saveEventsSuccessTest() throws Exception {
98+
@Test
99+
@DisplayName("외부 크롤러에서 이벤트 저장하기 성공 테스트")
100+
void saveEventsFromExternalSuccessTest() throws Exception {
74101
// Given
75-
when(eventService.saveEvents()).thenReturn(sampleEvents);
102+
CrawlingEventDtoList crawlingEventDtoList = new CrawlingEventDtoList();
103+
List<CrawlingEventDto> eventList = new ArrayList<>();
104+
105+
// 첫 번째 이벤트
106+
CrawlingEventDto dto1 = new CrawlingEventDto();
107+
dto1.setRanking(1);
108+
dto1.setGenre("콘서트");
109+
dto1.setTitle("Sample Concert");
110+
dto1.setPlace("Seoul Arena");
111+
dto1.setDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy.M.d")) + " ~ " +
112+
LocalDate.now().plusDays(30).format(DateTimeFormatter.ofPattern("yyyy.M.d")));
113+
dto1.setImage("http://example.com/image.jpg");
114+
115+
// 두 번째 이벤트
116+
CrawlingEventDto dto2 = new CrawlingEventDto();
117+
dto2.setRanking(2);
118+
dto2.setGenre("뮤지컬");
119+
dto2.setTitle("Sample Musical");
120+
dto2.setPlace("LG Arts Center");
121+
dto2.setDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy.M.d")) + " ~ " +
122+
LocalDate.now().plusDays(60).format(DateTimeFormatter.ofPattern("yyyy.M.d")));
123+
dto2.setImage("http://example.com/musical.jpg");
124+
125+
eventList.add(dto1);
126+
eventList.add(dto2);
127+
crawlingEventDtoList.setEvents(eventList);
128+
129+
// 요청 본문 JSON 문자열로 직렬화
130+
String requestBody = objectMapper.writeValueAsString(crawlingEventDtoList);
131+
132+
// HMAC 서명 생성
133+
String signature = HmacUtil.hmacSha256(requestBody, SECRET_KEY);
134+
135+
// Mock HttpServletRequest 설정
136+
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
137+
when(mockRequest.getHeader("X-Signature")).thenReturn(signature);
138+
139+
// EventService의 saveEvents 메서드 모킹
140+
when(eventService.saveEvents(any(CrawlingEventDtoList.class))).thenReturn(sampleEvents);
76141

77142
// When
78-
ApiResponseDto<List<EventDto>> response = eventController.saveEvents();
143+
ApiResponseDto<List<EventDto>> response = eventController.saveEventsFromExternal(mockRequest, crawlingEventDtoList);
79144

80145
// Then
81146
assertEquals(HttpStatus.OK.value(), response.getStatus());
82147
assertEquals(sampleEvents.size(), response.getData().size());
83148
assertEquals(sampleEvents.get(0).getTitle(), response.getData().get(0).getTitle());
84-
}*/
149+
assertEquals(sampleEvents.get(1).getTitle(), response.getData().get(1).getTitle());
150+
151+
// EventService의 saveEvents 메서드가 호출되었는지 확인
152+
verify(eventService).saveEvents(any(CrawlingEventDtoList.class));
153+
154+
// 헤더에서 시그니처를 가져왔는지 확인
155+
verify(mockRequest).getHeader("X-Signature");
156+
}
157+
158+
159+
@Test
160+
@DisplayName("외부 크롤러에서 이벤트 저장 시 HMAC 검증 실패 테스트")
161+
void saveEventsFromExternalHmacFailureTest() throws Exception {
162+
// Given
163+
CrawlingEventDtoList crawlingEventDtoList = new CrawlingEventDtoList();
164+
List<CrawlingEventDto> eventList = new ArrayList<>();
165+
166+
CrawlingEventDto dto = new CrawlingEventDto();
167+
dto.setRanking(1);
168+
dto.setGenre("콘서트");
169+
dto.setTitle("Sample Concert");
170+
dto.setPlace("Seoul Arena");
171+
dto.setDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy.M.d")) + " ~ " +
172+
LocalDate.now().plusDays(30).format(DateTimeFormatter.ofPattern("yyyy.M.d")));
173+
dto.setImage("http://example.com/image.jpg");
174+
175+
eventList.add(dto);
176+
crawlingEventDtoList.setEvents(eventList);
177+
178+
// 요청 본문 JSON 문자열로 직렬화
179+
String requestBody = objectMapper.writeValueAsString(crawlingEventDtoList);
180+
181+
// 잘못된 서명 설정
182+
String invalidSignature = "invalid_signature";
183+
184+
// Mock HttpServletRequest 설정
185+
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
186+
when(mockRequest.getHeader("X-Signature")).thenReturn(invalidSignature);
187+
when(mockRequest.getRequestURI()).thenReturn("/api/events/external");
188+
189+
// When & Then
190+
assertThrows(Exception.class, () -> {
191+
eventController.saveEventsFromExternal(mockRequest, crawlingEventDtoList);
192+
});
193+
194+
// EventService의 saveEvents 메서드가 호출되지 않았는지 확인
195+
verify(eventService, never()).saveEvents(any(CrawlingEventDtoList.class));
196+
197+
}
198+
85199

86200
@Test
87201
@DisplayName("이벤트 API 엔드포인트 GET 접근 테스트")
@@ -93,13 +207,61 @@ void getEventsEndpointTest() throws Exception {
93207
mockMvc.perform(get("/api/events")).andExpect(status().isOk());
94208
}
95209

96-
/*@Test
210+
@Test
97211
@DisplayName("이벤트 API 엔드포인트 POST 접근 테스트")
98212
void saveEventsEndpointTest() throws Exception {
99213
// Given
100-
when(eventService.saveEvents()).thenReturn(sampleEvents);
214+
CrawlingEventDtoList crawlingEventDtoList = new CrawlingEventDtoList();
215+
CrawlingEventDto event1 = new CrawlingEventDto();
216+
event1.setRanking(1);
217+
event1.setGenre("콘서트");
218+
event1.setTitle("Sample Concert");
219+
event1.setPlace("Seoul Arena");
220+
event1.setDate("2025.05.11 ~ 2025.06.11");
221+
event1.setImage("http://example.com/image.jpg");
222+
223+
CrawlingEventDto event2 = new CrawlingEventDto();
224+
event2.setRanking(2);
225+
event2.setGenre("뮤지컬");
226+
event2.setTitle("Sample Musical");
227+
event2.setPlace("LG Arts Center");
228+
event2.setDate("2025.05.11 ~ 2025.07.11");
229+
event2.setImage("http://example.com/musical.jpg");
230+
231+
List<CrawlingEventDto> eventList = Arrays.asList(event1, event2);
232+
crawlingEventDtoList.setEvents(eventList);
233+
234+
// 요청 본문 JSON 문자열로 직렬화
235+
String requestBody = objectMapper.writeValueAsString(crawlingEventDtoList);
236+
237+
// HMAC 서명 생성
238+
String signature = HmacUtil.hmacSha256(requestBody, SECRET_KEY);
239+
240+
// Mock HttpServletRequest 설정
241+
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
242+
lenient().when(mockRequest.getHeader("X-Signature")).thenReturn(signature);
243+
244+
// EventService의 saveEvents 메서드 모킹
245+
when(eventService.saveEvents(any(CrawlingEventDtoList.class))).thenReturn(sampleEvents);
101246

102247
// When & Then
103-
mockMvc.perform(post("/api/events")).andExpect(status().isOk());
104-
}*/
248+
mockMvc.perform(post("/api/events/external")
249+
.contentType("application/json")
250+
.content(requestBody)
251+
.header("X-Signature", signature))
252+
.andExpect(status().isOk()); // 응답 상태가 200인지 확인
253+
}
254+
255+
256+
257+
private void injectSecretKey(EventController controller, String secretKey) {
258+
try {
259+
Field field = EventController.class.getDeclaredField("SECRET_KEY");
260+
field.setAccessible(true);
261+
field.set(controller, secretKey);
262+
} catch (Exception e) {
263+
throw new RuntimeException("Failed to inject secret key into controller", e);
264+
}
265+
}
266+
105267
}

0 commit comments

Comments
 (0)