1+ package BE_Elixir .Elixir .domain .recipe .controller ;
2+
3+ import BE_Elixir .Elixir .domain .ingredient .entity .Ingredient ;
4+ import BE_Elixir .Elixir .domain .member .entity .MemberDetails ;
5+ import BE_Elixir .Elixir .domain .recipe .dto .response .RecipeHomeResponseDTO ;
6+ import BE_Elixir .Elixir .domain .recipe .entity .Material ;
7+ import BE_Elixir .Elixir .domain .recipe .entity .RecipeIngredient ;
8+ import org .springframework .data .domain .Page ;
9+ import org .springframework .data .domain .PageImpl ;
10+ import org .springframework .data .domain .PageRequest ;
11+ import org .springframework .data .domain .Pageable ;
12+ import org .springframework .data .domain .Sort ;
13+ import org .junit .jupiter .api .Test ;
14+ import BE_Elixir .Elixir .domain .member .entity .Member ;
15+ import BE_Elixir .Elixir .domain .recipe .dto .response .RecipeDetailResponseDTO ;
16+ import BE_Elixir .Elixir .domain .recipe .entity .Recipe ;
17+ import BE_Elixir .Elixir .domain .recipe .repository .RecipeRepository ;
18+ import BE_Elixir .Elixir .domain .recipe .service .RecipeService ;
19+ import BE_Elixir .Elixir .global .enums .CategorySlowAging ;
20+ import BE_Elixir .Elixir .global .enums .CategoryType ;
21+ import BE_Elixir .Elixir .global .enums .Difficulty ;
22+ import org .junit .jupiter .api .DisplayName ;
23+ import org .springframework .beans .factory .annotation .Autowired ;
24+ import org .springframework .boot .test .autoconfigure .web .servlet .WebMvcTest ;
25+ import org .springframework .http .MediaType ;
26+ import org .springframework .security .authentication .UsernamePasswordAuthenticationToken ;
27+ import org .springframework .security .core .context .SecurityContextHolder ;
28+ import org .springframework .test .context .bean .override .mockito .MockitoBean ;
29+ import org .springframework .test .web .servlet .MockMvc ;
30+ import org .springframework .test .web .servlet .ResultActions ;
31+
32+ import java .time .LocalDateTime ;
33+ import java .util .List ;
34+
35+ import static org .mockito .ArgumentMatchers .*;
36+ import static org .mockito .BDDMockito .given ;
37+ import static org .mockito .Mockito .mock ;
38+ import static org .mockito .Mockito .when ;
39+ import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .get ;
40+ import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .jsonPath ;
41+ import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .status ;
42+
43+ @ WebMvcTest (RecipeController .class )
44+ @ MockitoBean (types = {RecipeService .class , RecipeRepository .class })
45+ public class RecipeControllerTest {
46+
47+ @ Autowired
48+ private MockMvc mockMvc ;
49+ @ Autowired
50+ private RecipeService recipeService ;
51+
52+ private Member createMockMember () {
53+ Member member = mock (Member .class );
54+ when (member .getId ()).thenReturn (1L );
55+ return member ;
56+ }
57+
58+ // 인증 객체
59+ private void setAuthentication () {
60+ Member mockMember = createMockMember ();
61+ MemberDetails memberDetails = new MemberDetails (mockMember );
62+
63+ UsernamePasswordAuthenticationToken authentication =
64+ new UsernamePasswordAuthenticationToken (memberDetails , null , List .of ());
65+ SecurityContextHolder .getContext ().setAuthentication (authentication );
66+ }
67+
68+ private Recipe createMockRecipe () {
69+ Recipe recipe = mock (Recipe .class );
70+ Member mockMember = createMockMember ();
71+
72+ when (recipe .getMember ()).thenReturn (mockMember );
73+ when (recipe .getId ()).thenReturn (1L );
74+ when (recipe .getTitle ()).thenReturn ("테스트 레시피" );
75+ when (recipe .getImageUrl ()).thenReturn ("https://example.com/image.jpg" );
76+ when (recipe .getDescription ()).thenReturn ("테스트 설명" );
77+ when (recipe .getCategorySlowAging ()).thenReturn (CategorySlowAging .항산화강화 );
78+ when (recipe .getCategoryType ()).thenReturn (CategoryType .한식 );
79+ when (recipe .getDifficulty ()).thenReturn (Difficulty .보통 );
80+ when (recipe .getTimeHours ()).thenReturn (1 );
81+ when (recipe .getTimeMinutes ()).thenReturn (30 );
82+
83+ RecipeIngredient mockTag = mock (RecipeIngredient .class );
84+ Ingredient mockIngredient = mock (Ingredient .class );
85+ when (mockIngredient .getId ()).thenReturn (1L );
86+ when (mockTag .getIngredient ()).thenReturn (mockIngredient );
87+ when (recipe .getIngredientTags ()).thenReturn (List .of (mockTag ));
88+
89+ Material mockMaterial = mock (Material .class );
90+ when (mockMaterial .getName ()).thenReturn ("재료/양념 1" );
91+ when (mockMaterial .getValue ()).thenReturn ("100" );
92+ when (mockMaterial .getUnit ()).thenReturn ("g" );
93+ when (recipe .getIngredients ()).thenReturn (List .of (mockMaterial ));
94+ when (recipe .getSeasonings ()).thenReturn (List .of (mockMaterial ));
95+
96+ when (recipe .getStepDescriptions ()).thenReturn (List .of ("1단계 설명" ));
97+ when (recipe .getStepImageUrls ()).thenReturn (List .of ("https://example.com/step1.jpg" ));
98+ when (recipe .getTips ()).thenReturn ("팁" );
99+ when (recipe .getLikes ()).thenReturn (10 );
100+ when (recipe .getCreatedAt ()).thenReturn (LocalDateTime .now ().minusDays (1 ));
101+ when (recipe .getUpdatedAt ()).thenReturn (LocalDateTime .now ());
102+ when (recipe .getAllergy_우유 ()).thenReturn (true );
103+ when (recipe .getAllergy_밀 ()).thenReturn (true );
104+ return recipe ;
105+ }
106+
107+ @ Test
108+ @ DisplayName ("레시피_등록" )
109+ void createRecipe () throws Exception {
110+ }
111+
112+ @ Test
113+ @ DisplayName ("레시피_상세_조회" )
114+ void getRecipe () throws Exception {
115+ // given
116+ String url = "/api/recipe/1" ;
117+ setAuthentication ();
118+ Recipe recipe = createMockRecipe ();
119+
120+ RecipeDetailResponseDTO dto = new RecipeDetailResponseDTO (
121+ recipe ,
122+ true ,
123+ false ,
124+ false
125+ );
126+
127+ given (recipeService .getRecipeDetail (eq (1L ), any ())).willReturn (dto );
128+
129+ // when - API 호출
130+ final ResultActions result = mockMvc .perform (get (url )
131+ .accept (MediaType .APPLICATION_JSON ));
132+
133+ // then
134+ result .andExpect (status ().isOk ())
135+ .andExpect (jsonPath ("$.data.id" ).value (1L ))
136+ .andExpect (jsonPath ("$.data.title" ).value ("테스트 레시피" ))
137+ .andExpect (jsonPath ("$.data.likes" ).value (10 ))
138+ .andExpect (jsonPath ("$.data.ingredients[0].name" ).value ("재료/양념 1" ))
139+ .andExpect (jsonPath ("$.data.allergies" ).value (org .hamcrest .Matchers .containsInAnyOrder ("우유" , "밀" )));
140+ }
141+
142+ @ Test
143+ @ DisplayName ("전체_레시피_목록_조회" )
144+ void getRecipes () throws Exception {
145+ // given
146+ String url = "/api/recipe" ;
147+ setAuthentication ();
148+
149+ RecipeHomeResponseDTO dto1 = mock (RecipeHomeResponseDTO .class );
150+ RecipeHomeResponseDTO dto2 = mock (RecipeHomeResponseDTO .class );
151+ List <RecipeHomeResponseDTO > content = List .of (dto1 , dto2 );
152+ Pageable pageable = PageRequest .of (0 , 10 , Sort .by ("createdAt" ).descending ());
153+ Page <RecipeHomeResponseDTO > page = new PageImpl <>(content , pageable , content .size ());
154+ given (recipeService .getRecipeList (any (Pageable .class ), any ())).willReturn (page );
155+
156+ // when
157+ ResultActions result = mockMvc .perform (get (url )
158+ .param ("page" , "0" )
159+ .param ("size" , "10" )
160+ .accept (MediaType .APPLICATION_JSON ));
161+
162+ // then
163+ result .andExpect (status ().isOk ())
164+ .andExpect (jsonPath ("$.data.content" ).isArray ());
165+ }
166+
167+ @ Test
168+ void getSearchRecipe () {
169+ }
170+
171+ @ Test
172+ void getSearchKeyword () {
173+ }
174+
175+ @ Test
176+ void updateRecipe () {
177+ }
178+
179+ @ Test
180+ void deleteRecipe () {
181+ }
182+
183+ @ Test
184+ void getMyRecipes () {
185+ }
186+ }
0 commit comments