Skip to content

Commit 20b7a1f

Browse files
committed
test: MyHistoryController API 테스트 코드 작성
1 parent 8454e0c commit 20b7a1f

File tree

1 file changed

+349
-0
lines changed

1 file changed

+349
-0
lines changed
Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
package com.back.domain.myhistory.controller;
2+
3+
import com.back.domain.myhistory.dto.*;
4+
import com.back.domain.myhistory.service.MyHistoryService;
5+
import com.back.global.aspect.ResponseAspect;
6+
import com.back.global.jwt.JwtUtil;
7+
import com.back.global.rq.Rq;
8+
import com.back.global.security.SecurityUser;
9+
import org.junit.jupiter.api.AfterEach;
10+
import org.junit.jupiter.api.DisplayName;
11+
import org.junit.jupiter.api.Test;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
14+
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
15+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
16+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
17+
import org.springframework.context.annotation.Import;
18+
import org.springframework.http.MediaType;
19+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
20+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
21+
import org.springframework.security.core.context.SecurityContext;
22+
import org.springframework.security.core.context.SecurityContextHolder;
23+
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
24+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
25+
import org.springframework.test.web.servlet.MockMvc;
26+
import org.springframework.test.web.servlet.request.RequestPostProcessor;
27+
28+
import java.time.LocalDateTime;
29+
import java.time.format.DateTimeFormatter;
30+
import java.util.List;
31+
import java.util.Map;
32+
33+
import static org.mockito.ArgumentMatchers.eq;
34+
import static org.mockito.ArgumentMatchers.isNull;
35+
import static org.mockito.BDDMockito.given;
36+
import static org.mockito.Mockito.verify;
37+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
38+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
39+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
40+
41+
@WebMvcTest(MyHistoryController.class)
42+
@AutoConfigureMockMvc(addFilters = false)
43+
@Import(ResponseAspect.class)
44+
@ImportAutoConfiguration(AopAutoConfiguration.class)
45+
class MyHistoryControllerTest {
46+
47+
private static final DateTimeFormatter ISO_WITH_SECONDS = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
48+
49+
@Autowired
50+
private MockMvc mockMvc;
51+
52+
@MockitoBean
53+
private MyHistoryService myHistoryService;
54+
55+
@MockitoBean
56+
private JwtUtil jwtUtil;
57+
58+
@MockitoBean
59+
private Rq rq;
60+
61+
@AfterEach
62+
void clearSecurityContext() {
63+
SecurityContextHolder.clearContext();
64+
}
65+
66+
private SecurityUser createPrincipal(Long userId) {
67+
return new SecurityUser(
68+
userId,
69+
"user" + userId + "@example.com",
70+
"user" + userId,
71+
false,
72+
List.of(new SimpleGrantedAuthority("ROLE_USER")),
73+
Map.of()
74+
);
75+
}
76+
77+
private UsernamePasswordAuthenticationToken authenticated(SecurityUser principal) {
78+
return new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities());
79+
}
80+
81+
private RequestPostProcessor withPrincipal(SecurityUser principal) {
82+
return request -> {
83+
UsernamePasswordAuthenticationToken authentication = authenticated(principal);
84+
SecurityContext context = SecurityContextHolder.createEmptyContext();
85+
context.setAuthentication(authentication);
86+
SecurityContextHolder.setContext(context);
87+
request.setUserPrincipal(authentication);
88+
request.getSession(true)
89+
.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);
90+
return request;
91+
};
92+
}
93+
94+
@Test
95+
@DisplayName("Get my posts - first page")
96+
void getMyPosts_withoutCursor() throws Exception {
97+
SecurityUser principal = createPrincipal(10L);
98+
LocalDateTime createdAt = LocalDateTime.of(2025, 1, 1, 9, 0, 0);
99+
LocalDateTime nextCreatedAt = createdAt.minusMinutes(5);
100+
101+
MyHistoryPostItemDto item = MyHistoryPostItemDto.builder()
102+
.id(3L)
103+
.title("첫 글")
104+
.imageUrls(List.of("https://example.com/post.png"))
105+
.createdAt(createdAt)
106+
.likeCount(12)
107+
.commentCount(4)
108+
.build();
109+
110+
MyHistoryPostListDto responseDto = new MyHistoryPostListDto(
111+
List.of(item),
112+
true,
113+
nextCreatedAt,
114+
2L
115+
);
116+
117+
given(myHistoryService.getMyPosts(
118+
eq(principal.getId()),
119+
isNull(LocalDateTime.class),
120+
isNull(Long.class),
121+
eq(20)
122+
)).willReturn(responseDto);
123+
124+
mockMvc.perform(get("/me/posts")
125+
.with(withPrincipal(principal))
126+
.accept(MediaType.APPLICATION_JSON))
127+
.andExpect(status().isOk())
128+
.andExpect(jsonPath("$.code").value(200))
129+
.andExpect(jsonPath("$.message").value("success"))
130+
.andExpect(jsonPath("$.data.items[0].id").value(3L))
131+
.andExpect(jsonPath("$.data.items[0].title").value("첫 글"))
132+
.andExpect(jsonPath("$.data.items[0].imageUrls[0]").value("https://example.com/post.png"))
133+
.andExpect(jsonPath("$.data.items[0].createdAt").value(ISO_WITH_SECONDS.format(createdAt)))
134+
.andExpect(jsonPath("$.data.items[0].likeCount").value(12))
135+
.andExpect(jsonPath("$.data.items[0].commentCount").value(4))
136+
.andExpect(jsonPath("$.data.hasNext").value(true))
137+
.andExpect(jsonPath("$.data.nextCreatedAt").value(ISO_WITH_SECONDS.format(nextCreatedAt)))
138+
.andExpect(jsonPath("$.data.nextId").value(2L));
139+
140+
verify(myHistoryService).getMyPosts(
141+
eq(principal.getId()),
142+
isNull(LocalDateTime.class),
143+
isNull(Long.class),
144+
eq(20)
145+
);
146+
}
147+
148+
@Test
149+
@DisplayName("Get my posts - next page")
150+
void getMyPosts_withCursor() throws Exception {
151+
SecurityUser principal = createPrincipal(11L);
152+
LocalDateTime cursor = LocalDateTime.of(2025, 1, 5, 12, 30, 45);
153+
LocalDateTime createdAt = cursor.minusMinutes(2);
154+
155+
MyHistoryPostItemDto item = MyHistoryPostItemDto.builder()
156+
.id(9L)
157+
.title("다음 글")
158+
.imageUrls(List.of())
159+
.createdAt(createdAt)
160+
.likeCount(0)
161+
.commentCount(1)
162+
.build();
163+
164+
MyHistoryPostListDto responseDto = new MyHistoryPostListDto(
165+
List.of(item),
166+
false,
167+
null,
168+
null
169+
);
170+
171+
given(myHistoryService.getMyPosts(
172+
eq(principal.getId()),
173+
eq(cursor),
174+
eq(99L),
175+
eq(5)
176+
)).willReturn(responseDto);
177+
178+
mockMvc.perform(get("/me/posts")
179+
.with(withPrincipal(principal))
180+
.param("lastCreatedAt", cursor.toString())
181+
.param("lastId", "99")
182+
.param("limit", "5")
183+
.accept(MediaType.APPLICATION_JSON))
184+
.andExpect(status().isOk())
185+
.andExpect(jsonPath("$.data.items[0].id").value(9L))
186+
.andExpect(jsonPath("$.data.hasNext").value(false))
187+
.andExpect(jsonPath("$.data.nextCreatedAt").doesNotExist());
188+
189+
verify(myHistoryService).getMyPosts(
190+
eq(principal.getId()),
191+
eq(cursor),
192+
eq(99L),
193+
eq(5)
194+
);
195+
}
196+
197+
@Test
198+
@DisplayName("Get my comments")
199+
void getMyComments() throws Exception {
200+
SecurityUser principal = createPrincipal(12L);
201+
LocalDateTime createdAt = LocalDateTime.of(2025, 2, 1, 18, 0, 0);
202+
203+
MyHistoryCommentItemDto item = MyHistoryCommentItemDto.builder()
204+
.id(30L)
205+
.postId(100L)
206+
.postTitle("칵테일 후기")
207+
.content("정말 맛있어요")
208+
.createdAt(createdAt)
209+
.build();
210+
211+
MyHistoryCommentListDto responseDto = new MyHistoryCommentListDto(
212+
List.of(item),
213+
false,
214+
null,
215+
null
216+
);
217+
218+
given(myHistoryService.getMyComments(
219+
eq(principal.getId()),
220+
isNull(LocalDateTime.class),
221+
isNull(Long.class),
222+
eq(20)
223+
)).willReturn(responseDto);
224+
225+
mockMvc.perform(get("/me/comments")
226+
.with(withPrincipal(principal))
227+
.accept(MediaType.APPLICATION_JSON))
228+
.andExpect(status().isOk())
229+
.andExpect(jsonPath("$.data.items[0].id").value(30L))
230+
.andExpect(jsonPath("$.data.items[0].postId").value(100L))
231+
.andExpect(jsonPath("$.data.items[0].postTitle").value("칵테일 후기"))
232+
.andExpect(jsonPath("$.data.items[0].content").value("정말 맛있어요"))
233+
.andExpect(jsonPath("$.data.items[0].createdAt").value(ISO_WITH_SECONDS.format(createdAt)));
234+
235+
verify(myHistoryService).getMyComments(
236+
eq(principal.getId()),
237+
isNull(LocalDateTime.class),
238+
isNull(Long.class),
239+
eq(20)
240+
);
241+
}
242+
243+
@Test
244+
@DisplayName("Get my liked posts")
245+
void getMyLikedPosts() throws Exception {
246+
SecurityUser principal = createPrincipal(13L);
247+
LocalDateTime likedAt = LocalDateTime.of(2025, 3, 10, 21, 5, 0);
248+
249+
MyHistoryLikedPostItemDto item = MyHistoryLikedPostItemDto.builder()
250+
.id(70L)
251+
.title("봄 추천 칵테일")
252+
.imageUrls(List.of("https://example.com/spring.png"))
253+
.likedAt(likedAt)
254+
.likeCount(88)
255+
.commentCount(12)
256+
.build();
257+
258+
MyHistoryLikedPostListDto responseDto = new MyHistoryLikedPostListDto(
259+
List.of(item),
260+
true,
261+
likedAt.minusSeconds(30),
262+
55L
263+
);
264+
265+
given(myHistoryService.getMyLikedPosts(
266+
eq(principal.getId()),
267+
isNull(LocalDateTime.class),
268+
isNull(Long.class),
269+
eq(20)
270+
)).willReturn(responseDto);
271+
272+
mockMvc.perform(get("/me/likes")
273+
.with(withPrincipal(principal))
274+
.accept(MediaType.APPLICATION_JSON))
275+
.andExpect(status().isOk())
276+
.andExpect(jsonPath("$.data.items[0].id").value(70L))
277+
.andExpect(jsonPath("$.data.items[0].title").value("봄 추천 칵테일"))
278+
.andExpect(jsonPath("$.data.items[0].imageUrls[0]").value("https://example.com/spring.png"))
279+
.andExpect(jsonPath("$.data.items[0].likedAt").value(ISO_WITH_SECONDS.format(likedAt)))
280+
.andExpect(jsonPath("$.data.items[0].likeCount").value(88))
281+
.andExpect(jsonPath("$.data.items[0].commentCount").value(12))
282+
.andExpect(jsonPath("$.data.hasNext").value(true))
283+
.andExpect(jsonPath("$.data.nextId").value(55L));
284+
285+
verify(myHistoryService).getMyLikedPosts(
286+
eq(principal.getId()),
287+
isNull(LocalDateTime.class),
288+
isNull(Long.class),
289+
eq(20)
290+
);
291+
}
292+
293+
@Test
294+
@DisplayName("Go to my post detail")
295+
void goFromPost() throws Exception {
296+
SecurityUser principal = createPrincipal(14L);
297+
Long postId = 200L;
298+
MyHistoryPostGoResponseDto responseDto = new MyHistoryPostGoResponseDto(postId, "/posts/" + postId);
299+
300+
given(myHistoryService.getPostLinkFromMyPost(principal.getId(), postId)).willReturn(responseDto);
301+
302+
mockMvc.perform(get("/me/posts/{id}", postId)
303+
.with(withPrincipal(principal))
304+
.accept(MediaType.APPLICATION_JSON))
305+
.andExpect(status().isOk())
306+
.andExpect(jsonPath("$.data.postId").value(postId))
307+
.andExpect(jsonPath("$.data.postApiUrl").value("/posts/" + postId));
308+
309+
verify(myHistoryService).getPostLinkFromMyPost(principal.getId(), postId);
310+
}
311+
312+
@Test
313+
@DisplayName("Go to post from comment")
314+
void goFromComment() throws Exception {
315+
SecurityUser principal = createPrincipal(15L);
316+
Long commentId = 501L;
317+
MyHistoryCommentGoResponseDto responseDto = new MyHistoryCommentGoResponseDto(301L, "/posts/301");
318+
319+
given(myHistoryService.getPostLinkFromMyComment(principal.getId(), commentId)).willReturn(responseDto);
320+
321+
mockMvc.perform(get("/me/comments/{id}", commentId)
322+
.with(withPrincipal(principal))
323+
.accept(MediaType.APPLICATION_JSON))
324+
.andExpect(status().isOk())
325+
.andExpect(jsonPath("$.data.postId").value(301L))
326+
.andExpect(jsonPath("$.data.postApiUrl").value("/posts/301"));
327+
328+
verify(myHistoryService).getPostLinkFromMyComment(principal.getId(), commentId);
329+
}
330+
331+
@Test
332+
@DisplayName("Go to post from liked list")
333+
void goFromLikedPost() throws Exception {
334+
SecurityUser principal = createPrincipal(16L);
335+
Long likedPostId = 901L;
336+
MyHistoryPostGoResponseDto responseDto = new MyHistoryPostGoResponseDto(likedPostId, "/posts/" + likedPostId);
337+
338+
given(myHistoryService.getPostLinkFromMyLikedPost(principal.getId(), likedPostId)).willReturn(responseDto);
339+
340+
mockMvc.perform(get("/me/likes/{id}", likedPostId)
341+
.with(withPrincipal(principal))
342+
.accept(MediaType.APPLICATION_JSON))
343+
.andExpect(status().isOk())
344+
.andExpect(jsonPath("$.data.postId").value(likedPostId))
345+
.andExpect(jsonPath("$.data.postApiUrl").value("/posts/" + likedPostId));
346+
347+
verify(myHistoryService).getPostLinkFromMyLikedPost(principal.getId(), likedPostId);
348+
}
349+
}

0 commit comments

Comments
 (0)