Skip to content

Commit 1fd7aea

Browse files
committed
test: MyBarController API 테스트 코드 작성
1 parent 80a3d7d commit 1fd7aea

File tree

1 file changed

+241
-0
lines changed

1 file changed

+241
-0
lines changed
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
package com.back.domain.mybar.controller;
2+
3+
import com.back.domain.mybar.dto.MyBarItemResponseDto;
4+
import com.back.domain.mybar.dto.MyBarListResponseDto;
5+
import com.back.domain.mybar.service.MyBarService;
6+
import com.back.global.aspect.ResponseAspect;
7+
import com.back.global.jwt.JwtUtil;
8+
import com.back.global.rq.Rq;
9+
import com.back.global.security.SecurityUser;
10+
import java.time.LocalDateTime;
11+
import java.time.format.DateTimeFormatter;
12+
import java.util.List;
13+
import java.util.Map;
14+
import org.junit.jupiter.api.AfterEach;
15+
import org.junit.jupiter.api.DisplayName;
16+
import org.junit.jupiter.api.Test;
17+
import org.springframework.beans.factory.annotation.Autowired;
18+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
19+
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
20+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
21+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
22+
import org.springframework.context.annotation.Import;
23+
import org.springframework.http.MediaType;
24+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
25+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
26+
import org.springframework.security.core.context.SecurityContext;
27+
import org.springframework.security.core.context.SecurityContextHolder;
28+
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
29+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
30+
import org.springframework.test.web.servlet.MockMvc;
31+
import org.springframework.test.web.servlet.request.RequestPostProcessor;
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.BDDMockito.willDoNothing;
37+
import static org.mockito.Mockito.verify;
38+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
39+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
40+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
41+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
42+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
43+
44+
@WebMvcTest(MyBarController.class)
45+
@AutoConfigureMockMvc(addFilters = false)
46+
@Import(ResponseAspect.class)
47+
@ImportAutoConfiguration(AopAutoConfiguration.class)
48+
class MyBarControllerTest {
49+
50+
private static final DateTimeFormatter ISO_WITH_SECONDS = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
51+
52+
@Autowired
53+
private MockMvc mockMvc;
54+
55+
@MockitoBean
56+
private MyBarService myBarService;
57+
58+
@MockitoBean
59+
private JwtUtil jwtUtil;
60+
61+
@MockitoBean
62+
private Rq rq;
63+
64+
@AfterEach
65+
void clearSecurityContext() {
66+
SecurityContextHolder.clearContext();
67+
}
68+
69+
private SecurityUser createPrincipal(Long userId) {
70+
return new SecurityUser(
71+
userId,
72+
"user" + userId + "@example.com",
73+
"user" + userId,
74+
false,
75+
List.of(new SimpleGrantedAuthority("ROLE_USER")),
76+
Map.of()
77+
);
78+
}
79+
80+
private UsernamePasswordAuthenticationToken authenticated(SecurityUser principal) {
81+
return new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities());
82+
}
83+
84+
private RequestPostProcessor withPrincipal(SecurityUser principal) {
85+
return request -> {
86+
UsernamePasswordAuthenticationToken authentication = authenticated(principal);
87+
SecurityContext context = SecurityContextHolder.createEmptyContext();
88+
context.setAuthentication(authentication);
89+
SecurityContextHolder.setContext(context);
90+
request.setUserPrincipal(authentication);
91+
request.getSession(true)
92+
.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);
93+
return request;
94+
};
95+
}
96+
97+
@Test
98+
@DisplayName("Get my bar list - first page")
99+
void getMyBarList_withoutCursor() throws Exception {
100+
SecurityUser principal = createPrincipal(1L);
101+
LocalDateTime keptAt = LocalDateTime.of(2025, 1, 1, 10, 0);
102+
LocalDateTime createdAt = keptAt.minusDays(1);
103+
104+
MyBarItemResponseDto item = MyBarItemResponseDto.builder()
105+
.id(3L)
106+
.cocktailId(10L)
107+
.cocktailName("Margarita")
108+
.imageUrl("https://example.com/margarita.jpg")
109+
.createdAt(createdAt)
110+
.keptAt(keptAt)
111+
.build();
112+
113+
MyBarListResponseDto responseDto = new MyBarListResponseDto(
114+
List.of(item),
115+
true,
116+
keptAt.minusMinutes(5),
117+
2L
118+
);
119+
120+
given(myBarService.getMyBar(
121+
eq(principal.getId()),
122+
isNull(LocalDateTime.class),
123+
isNull(Long.class),
124+
eq(20)
125+
)).willReturn(responseDto);
126+
127+
mockMvc.perform(get("/me/bar")
128+
.with(withPrincipal(principal))
129+
.accept(MediaType.APPLICATION_JSON))
130+
.andExpect(status().isOk())
131+
.andExpect(jsonPath("$.code").value(200))
132+
.andExpect(jsonPath("$.message").value("success"))
133+
.andExpect(jsonPath("$.data.items[0].id").value(3L))
134+
.andExpect(jsonPath("$.data.items[0].cocktailId").value(10L))
135+
.andExpect(jsonPath("$.data.items[0].cocktailName").value("Margarita"))
136+
.andExpect(jsonPath("$.data.items[0].imageUrl").value("https://example.com/margarita.jpg"))
137+
.andExpect(jsonPath("$.data.items[0].createdAt").value(ISO_WITH_SECONDS.format(createdAt)))
138+
.andExpect(jsonPath("$.data.items[0].keptAt").value(ISO_WITH_SECONDS.format(keptAt)))
139+
.andExpect(jsonPath("$.data.hasNext").value(true))
140+
.andExpect(jsonPath("$.data.nextKeptAt").value(ISO_WITH_SECONDS.format(keptAt.minusMinutes(5))))
141+
.andExpect(jsonPath("$.data.nextId").value(2L));
142+
143+
verify(myBarService).getMyBar(
144+
eq(principal.getId()),
145+
isNull(LocalDateTime.class),
146+
isNull(Long.class),
147+
eq(20)
148+
);
149+
}
150+
151+
@Test
152+
@DisplayName("Get my bar list - next page")
153+
void getMyBarList_withCursor() throws Exception {
154+
SecurityUser principal = createPrincipal(7L);
155+
LocalDateTime cursorKeptAt = LocalDateTime.of(2025, 2, 10, 9, 30, 15);
156+
LocalDateTime itemKeptAt = cursorKeptAt.minusMinutes(1);
157+
LocalDateTime itemCreatedAt = itemKeptAt.minusDays(2);
158+
159+
MyBarItemResponseDto item = MyBarItemResponseDto.builder()
160+
.id(20L)
161+
.cocktailId(33L)
162+
.cocktailName("Negroni")
163+
.imageUrl("https://example.com/negroni.jpg")
164+
.createdAt(itemCreatedAt)
165+
.keptAt(itemKeptAt)
166+
.build();
167+
168+
MyBarListResponseDto responseDto = new MyBarListResponseDto(
169+
List.of(item),
170+
false,
171+
null,
172+
null
173+
);
174+
175+
given(myBarService.getMyBar(
176+
eq(principal.getId()),
177+
eq(cursorKeptAt),
178+
eq(99L),
179+
eq(5)
180+
)).willReturn(responseDto);
181+
182+
mockMvc.perform(get("/me/bar")
183+
.with(withPrincipal(principal))
184+
.param("lastKeptAt", cursorKeptAt.toString())
185+
.param("lastId", "99")
186+
.param("limit", "5")
187+
.accept(MediaType.APPLICATION_JSON))
188+
.andExpect(status().isOk())
189+
.andExpect(jsonPath("$.code").value(200))
190+
.andExpect(jsonPath("$.message").value("success"))
191+
.andExpect(jsonPath("$.data.items[0].id").value(20L))
192+
.andExpect(jsonPath("$.data.items[0].cocktailName").value("Negroni"))
193+
.andExpect(jsonPath("$.data.hasNext").value(false))
194+
.andExpect(jsonPath("$.data.nextKeptAt").doesNotExist());
195+
196+
verify(myBarService).getMyBar(
197+
eq(principal.getId()),
198+
eq(cursorKeptAt),
199+
eq(99L),
200+
eq(5)
201+
);
202+
}
203+
204+
@Test
205+
@DisplayName("Keep cocktail")
206+
void keepCocktail() throws Exception {
207+
SecurityUser principal = createPrincipal(11L);
208+
Long cocktailId = 42L;
209+
210+
willDoNothing().given(myBarService).keep(principal.getId(), cocktailId);
211+
212+
mockMvc.perform(post("/me/bar/{cocktailId}/keep", cocktailId)
213+
.with(withPrincipal(principal))
214+
.accept(MediaType.APPLICATION_JSON))
215+
.andExpect(status().isCreated())
216+
.andExpect(jsonPath("$.code").value(201))
217+
.andExpect(jsonPath("$.message").value("kept"))
218+
.andExpect(jsonPath("$.data").doesNotExist());
219+
220+
verify(myBarService).keep(principal.getId(), cocktailId);
221+
}
222+
223+
@Test
224+
@DisplayName("Unkeep cocktail")
225+
void unkeepCocktail() throws Exception {
226+
SecurityUser principal = createPrincipal(12L);
227+
Long cocktailId = 77L;
228+
229+
willDoNothing().given(myBarService).unkeep(principal.getId(), cocktailId);
230+
231+
mockMvc.perform(delete("/me/bar/{cocktailId}/keep", cocktailId)
232+
.with(withPrincipal(principal))
233+
.accept(MediaType.APPLICATION_JSON))
234+
.andExpect(status().isOk())
235+
.andExpect(jsonPath("$.code").value(200))
236+
.andExpect(jsonPath("$.message").value("deleted"))
237+
.andExpect(jsonPath("$.data").doesNotExist());
238+
239+
verify(myBarService).unkeep(principal.getId(), cocktailId);
240+
}
241+
}

0 commit comments

Comments
 (0)