Skip to content

Commit 83fe8f5

Browse files
authored
[test]Cocktail, CocktailComment controller testCase (#183)
* fix : bugs of testCase, init data * fix : bug * test cocktail controller * Cocktail Comment Controller test * cocktailController searchAndFilter test
1 parent d29952b commit 83fe8f5

File tree

5 files changed

+248
-4
lines changed

5 files changed

+248
-4
lines changed

src/main/java/com/back/domain/cocktail/comment/dto/CocktailCommentResponseDto.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public record CocktailCommentResponseDto(
99
Long commentId,
10-
Long postId,
10+
Long cocktailId,
1111
String userNickName,
1212
LocalDateTime createdAt,
1313
LocalDateTime updatedAt,

src/main/java/com/back/domain/cocktail/controller/CocktailController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ public RsData<List<CocktailSearchResponseDto>> searchAndFilter(
5656
// 서비스 호출
5757
List<CocktailSearchResponseDto> searchResults = cocktailService.searchAndFilter(cocktailSearchRequestDto);
5858

59-
// RsData로 통일된 응답 반환
6059
return RsData.successOf(searchResults);
6160
}
6261
}

src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public ResponseEntity<RsData<Map<String, String>>> getShareLink(@PathVariable Lo
2424
.map(cocktail -> {
2525
Map<String, String> response = Map.of(
2626
// 공유 URL
27-
"url", "https://www.ssoul.o-r.kr/cocktails/" + cocktail.getId(),
27+
"url", "https://www.ssoul.life/cocktails/" + cocktail.getId(),
2828
// 공유 제목
2929
"title", cocktail.getCocktailName(),
3030
// 공유 이미지 (선택)
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
package com.back.domain.cocktail.comment.controller;
2+
3+
import com.back.domain.cocktail.comment.dto.CocktailCommentCreateRequestDto;
4+
import com.back.domain.cocktail.comment.dto.CocktailCommentResponseDto;
5+
import com.back.domain.cocktail.comment.dto.CocktailCommentUpdateRequestDto;
6+
import com.back.domain.cocktail.comment.service.CocktailCommentService;
7+
import com.back.domain.post.comment.enums.CommentStatus;
8+
import com.back.global.jwt.JwtUtil;
9+
import com.back.global.rq.Rq;
10+
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import org.junit.jupiter.api.DisplayName;
12+
import org.junit.jupiter.api.Test;
13+
import org.springframework.beans.factory.annotation.Autowired;
14+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
15+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
16+
import org.springframework.http.MediaType;
17+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
18+
import org.springframework.test.web.servlet.MockMvc;
19+
20+
import java.time.LocalDateTime;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
24+
import static org.hamcrest.Matchers.hasSize;
25+
import static org.hamcrest.Matchers.nullValue;
26+
import static org.mockito.ArgumentMatchers.*;
27+
import static org.mockito.BDDMockito.given;
28+
import static org.mockito.BDDMockito.willDoNothing;
29+
import static org.mockito.Mockito.verify;
30+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
31+
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
32+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
33+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
34+
35+
@WebMvcTest(CocktailCommentController.class)
36+
@AutoConfigureMockMvc(addFilters = false)
37+
public class CocktailCommentControllerTest {
38+
39+
@Autowired
40+
private MockMvc mockMvc;
41+
@Autowired
42+
private ObjectMapper objectMapper;
43+
@MockitoBean
44+
private CocktailCommentService cocktailCommentService;
45+
@MockitoBean
46+
private JwtUtil jwtUtil;
47+
@MockitoBean
48+
private Rq rq;
49+
50+
private CocktailCommentResponseDto createSampleResponseDto(Long id) {
51+
return new CocktailCommentResponseDto(
52+
id,
53+
1L,
54+
"테스트유저" + id,
55+
LocalDateTime.now(),
56+
LocalDateTime.now(),
57+
CommentStatus.PUBLIC,
58+
"테스트 내용" + id
59+
);
60+
}
61+
62+
@Test
63+
@DisplayName("칵테일 댓글 작성 API 테스트")
64+
void t1() throws Exception {
65+
// given
66+
CocktailCommentCreateRequestDto requestDto = new CocktailCommentCreateRequestDto(
67+
CommentStatus.PUBLIC,
68+
"테스트 내용1"
69+
);
70+
CocktailCommentResponseDto responseDto = createSampleResponseDto(1L);
71+
given(cocktailCommentService.createCocktailComment(anyLong(), any(CocktailCommentCreateRequestDto.class))).willReturn(responseDto);
72+
73+
// when & then
74+
mockMvc.perform(post("/cocktails/{cocktailId}/comments", 1L)
75+
.contentType(MediaType.APPLICATION_JSON)
76+
.content(objectMapper.writeValueAsString(requestDto)))
77+
.andExpect(status().isOk())
78+
.andExpect(jsonPath("$.data.commentId").value(1L))
79+
.andExpect(jsonPath("$.data.cocktailId").value(1L))
80+
.andExpect(jsonPath("$.data.userNickName").value("테스트유저1"))
81+
.andExpect(jsonPath("$.data.status").value("PUBLIC"))
82+
.andExpect(jsonPath("$.data.content").value("테스트 내용1"))
83+
.andDo(print());
84+
}
85+
86+
@Test
87+
@DisplayName("칵테일 댓글 다건 조회 API 테스트")
88+
void t2() throws Exception {
89+
// given
90+
List<CocktailCommentResponseDto> firstPage = new ArrayList<>();
91+
for (long i = 30; i >= 21; i--) {
92+
firstPage.add(createSampleResponseDto(i));
93+
}
94+
95+
List<CocktailCommentResponseDto> secondPage = new ArrayList<>();
96+
for (long i = 20; i >= 11; i--) {
97+
secondPage.add(createSampleResponseDto(i));
98+
}
99+
100+
given(cocktailCommentService.getCocktailComments(1L, null)).willReturn(firstPage); // 첫 호출(lastId 없음)
101+
given(cocktailCommentService.getCocktailComments(1L, 21L)).willReturn(secondPage);
102+
103+
// when & then
104+
mockMvc.perform(get("/cocktails/{cocktailId}/comments", 1L))
105+
.andExpect(status().isOk())
106+
.andExpect(jsonPath("$.data", hasSize(10)))
107+
.andExpect(jsonPath("$.data[0].commentId").value(30))
108+
.andExpect(jsonPath("$.data[0].cocktailId").value(1L))
109+
.andExpect(jsonPath("$.data[0].userNickName").value("테스트유저30"))
110+
.andExpect(jsonPath("$.data[0].status").value("PUBLIC"))
111+
.andExpect(jsonPath("$.data[0].content").value("테스트 내용30"))
112+
.andDo(print());
113+
114+
mockMvc.perform(get("/cocktails/{cocktailId}/comments", 1L).param("lastId", "21"))
115+
.andExpect(status().isOk())
116+
.andExpect(jsonPath("$.data", hasSize(10)))
117+
.andExpect(jsonPath("$.data[0].commentId").value(20))
118+
.andExpect(jsonPath("$.data[0].cocktailId").value(1L))
119+
.andExpect(jsonPath("$.data[0].userNickName").value("테스트유저20"))
120+
.andExpect(jsonPath("$.data[0].status").value("PUBLIC"))
121+
.andExpect(jsonPath("$.data[0].content").value("테스트 내용20"))
122+
.andDo(print());
123+
}
124+
125+
@Test
126+
@DisplayName("칵테일 댓글 단건 조회 API 테스트")
127+
void t3() throws Exception {
128+
// given
129+
Long cocktailId = 1L;
130+
Long cocktailCommentId = 1L;
131+
CocktailCommentResponseDto responseDto = createSampleResponseDto(cocktailCommentId);
132+
given(cocktailCommentService.getCocktailComment(cocktailId, cocktailCommentId)).willReturn(responseDto);
133+
134+
// when & then
135+
mockMvc.perform(get("/cocktails/{cocktailId}/comments/{cocktailCommentId}", cocktailId, cocktailCommentId))
136+
.andExpect(status().isOk())
137+
.andExpect(jsonPath("$.data.commentId").value(cocktailCommentId))
138+
.andExpect(jsonPath("$.data.cocktailId").value(cocktailId))
139+
.andExpect(jsonPath("$.data.userNickName").value("테스트유저1"))
140+
.andExpect(jsonPath("$.data.status").value("PUBLIC"))
141+
.andExpect(jsonPath("$.data.content").value("테스트 내용1"))
142+
.andDo(print());
143+
}
144+
145+
@Test
146+
@DisplayName("칵테일 댓글 수정 API 테스트")
147+
void t4() throws Exception {
148+
// given
149+
Long cocktailId = 1L;
150+
Long cocktailCommentId = 1L;
151+
152+
CocktailCommentUpdateRequestDto requestDto = new CocktailCommentUpdateRequestDto(
153+
CommentStatus.PUBLIC,
154+
"수정된 내용" + cocktailCommentId
155+
);
156+
157+
CocktailCommentResponseDto responseDto = new CocktailCommentResponseDto(
158+
cocktailCommentId,
159+
cocktailId,
160+
"테스트유저" + cocktailCommentId,
161+
LocalDateTime.now(),
162+
LocalDateTime.now(),
163+
CommentStatus.PUBLIC,
164+
"수정된 내용" + cocktailCommentId
165+
);
166+
167+
given(cocktailCommentService.updateCocktailComment(eq(cocktailId), eq(cocktailCommentId), any(CocktailCommentUpdateRequestDto.class)))
168+
.willReturn(responseDto);
169+
170+
// when & then
171+
mockMvc.perform(patch("/cocktails/{cocktailId}/comments/{cocktailCommentId}", cocktailId, cocktailCommentId)
172+
.contentType(MediaType.APPLICATION_JSON)
173+
.content(objectMapper.writeValueAsString(requestDto)))
174+
.andExpect(status().isOk())
175+
.andExpect(jsonPath("$.data.commentId").value(cocktailCommentId))
176+
.andExpect(jsonPath("$.data.cocktailId").value(cocktailId))
177+
.andExpect(jsonPath("$.data.userNickName").value("테스트유저" + cocktailCommentId))
178+
.andExpect(jsonPath("$.data.status").value("PUBLIC"))
179+
.andExpect(jsonPath("$.data.content").value("수정된 내용" + cocktailCommentId))
180+
.andDo(print());
181+
}
182+
183+
@Test
184+
@DisplayName("칵테일 댓글 삭제 API 테스트")
185+
void t5() throws Exception {
186+
// given
187+
Long cocktailId = 1L;
188+
Long cocktailCommentId = 1L;
189+
190+
willDoNothing().given(cocktailCommentService).deleteCocktailComment(cocktailId, cocktailCommentId);
191+
192+
// when & then
193+
mockMvc.perform(delete("/cocktails/{cocktailId}/comments/{cocktailCommentId}", cocktailId, cocktailCommentId))
194+
.andExpect(status().isOk())
195+
.andExpect(jsonPath("$.message").value("success"))
196+
.andExpect(jsonPath("$.data").value(nullValue())) // null 이므로 empty 체크 가능
197+
.andDo(print());
198+
199+
// 추가 검증: 서비스 메소드가 정확히 호출됐는지 확인
200+
verify(cocktailCommentService).deleteCocktailComment(cocktailId, cocktailCommentId);
201+
}
202+
}

src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package com.back.domain.cocktail.controller;
22

3+
import com.back.domain.cocktail.dto.CocktailSearchRequestDto;
34
import com.back.domain.cocktail.entity.Cocktail;
45
import com.back.domain.cocktail.enums.AlcoholBaseType;
56
import com.back.domain.cocktail.enums.AlcoholStrength;
67
import com.back.domain.cocktail.enums.CocktailType;
78
import com.back.domain.cocktail.repository.CocktailRepository;
89
import com.back.domain.user.service.UserService;
910
import com.back.global.rq.Rq;
11+
import com.back.global.standard.util.Ut;
1012
import jakarta.servlet.http.HttpServletRequest;
1113
import jakarta.servlet.http.HttpServletResponse;
1214
import org.junit.jupiter.api.DisplayName;
@@ -27,6 +29,7 @@
2729
import java.time.LocalDateTime;
2830

2931
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
32+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
3033
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
3134
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
3235
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -138,6 +141,47 @@ void t4() throws Exception {
138141
.andExpect(jsonPath("$.data").isArray());
139142
}
140143

144+
@Test
145+
@DisplayName("칵테일 검색 및 필터링")
146+
void t5() throws Exception {
147+
// given: DB에 칵테일 저장
148+
Cocktail savedCocktail = cocktailRepository.save(
149+
Cocktail.builder()
150+
.cocktailName("모히토")
151+
.alcoholStrength(AlcoholStrength.WEAK)
152+
.cocktailType(CocktailType.SHORT)
153+
.alcoholBaseType(AlcoholBaseType.RUM)
154+
.cocktailImgUrl("https://example.com/image.jpg")
155+
.cocktailStory("상쾌한 라임과 민트")
156+
.ingredient("라임, 민트, 럼, 설탕, 탄산수")
157+
.recipe("라임과 민트를 섞고 럼을 넣고 탄산수로 완성")
158+
.createdAt(LocalDateTime.now())
159+
.updatedAt(LocalDateTime.now())
160+
.build()
161+
);
162+
163+
// 검색 조건 (키워드: "모히토")
164+
CocktailSearchRequestDto requestDto = new CocktailSearchRequestDto();
165+
requestDto.setKeyword("모히토");
166+
167+
// when: POST 요청
168+
ResultActions resultActions = mvc.perform(
169+
post("/cocktails/search")
170+
.contentType(MediaType.APPLICATION_JSON)
171+
.content(Ut.json.toString(requestDto))
172+
).andDo(print());
173+
174+
// then: 상태코드, JSON 구조 검증
175+
resultActions
176+
.andExpect(status().isOk())
177+
.andExpect(jsonPath("$.code").value(200))
178+
.andExpect(jsonPath("$.message").value("success"))
179+
.andExpect(jsonPath("$.data[0].cocktailName").value("모히토"))
180+
.andExpect(jsonPath("$.data[0].alcoholStrength").value("WEAK"))
181+
.andExpect(jsonPath("$.data[0].cocktailType").value("SHORT"))
182+
.andExpect(jsonPath("$.data[0].alcoholBaseType").value("RUM"));
183+
}
184+
141185
@TestConfiguration
142186
static class TestConfig {
143187
@Bean
@@ -149,5 +193,4 @@ public Rq rq() {
149193
return new Rq(req, resp, userService);
150194
}
151195
}
152-
153196
}

0 commit comments

Comments
 (0)