11package com .back .domain .file .controller ;
22
3- import com .back .domain .board .post .entity .Post ;
4- import com .back .domain .board .post .repository .PostRepository ;
53import com .back .domain .file .config .S3MockConfig ;
4+ import com .back .domain .file .dto .FileUploadResponseDto ;
5+ import com .back .domain .file .service .FileService ;
66import com .back .domain .user .entity .User ;
77import com .back .domain .user .entity .UserProfile ;
88import com .back .domain .user .entity .UserStatus ;
2525
2626import java .time .LocalDate ;
2727
28- import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .multipart ;
28+ import static org .hamcrest .Matchers .not ;
29+ import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .*;
2930import static org .springframework .test .web .servlet .result .MockMvcResultHandlers .print ;
3031import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .jsonPath ;
3132import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .status ;
@@ -49,10 +50,10 @@ class FileControllerTest {
4950 private PasswordEncoder passwordEncoder ;
5051
5152 @ Autowired
52- private PostRepository postRepository ;
53+ private TestJwtTokenProvider testJwtTokenProvider ;
5354
5455 @ Autowired
55- private TestJwtTokenProvider testJwtTokenProvider ;
56+ private FileService fileService ;
5657
5758 private String generateAccessToken (User user ) {
5859 return testJwtTokenProvider .createAccessToken (
@@ -78,9 +79,6 @@ void uploadFile_success() throws Exception {
7879
7980 String accessToken = generateAccessToken (user );
8081
81- Post post = new Post (user , "첫 글" , "내용" , null );
82- postRepository .save (post );
83-
8482 MockMultipartFile multipartFile = new MockMultipartFile (
8583 "multipartFile" ,
8684 "test.png" ,
@@ -92,8 +90,6 @@ void uploadFile_success() throws Exception {
9290 ResultActions resultActions = mvc .perform (
9391 multipart ("/api/file/upload" ) // 👈 post() 대신 multipart() 사용
9492 .file (multipartFile ) // 파일 필드
95- .param ("entityType" , "POST" ) // DTO 필드 매핑
96- .param ("entityId" , post .getId ().toString ())
9793 .header ("Authorization" , "Bearer " + accessToken )
9894 .characterEncoding ("UTF-8" )
9995 );
@@ -105,7 +101,7 @@ void uploadFile_success() throws Exception {
105101 }
106102
107103 @ Test
108- @ DisplayName ("파일 업로드 실패 - 파일이 없는 경우" )
104+ @ DisplayName ("파일 업로드 실패 - 파일 입력이 없는 경우" )
109105 void uploadFile_fail_noFile () throws Exception {
110106 // given
111107 User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
@@ -115,14 +111,9 @@ void uploadFile_fail_noFile() throws Exception {
115111
116112 String accessToken = generateAccessToken (user );
117113
118- Post post = new Post (user , "첫 글" , "내용" , null );
119- postRepository .save (post );
120-
121114 // when
122115 ResultActions resultActions = mvc .perform (
123116 multipart ("/api/file/upload" ) // 👈 post() 대신 multipart() 사용
124- .param ("entityType" , "POST" ) // DTO 필드 매핑
125- .param ("entityId" , post .getId ().toString ())
126117 .header ("Authorization" , "Bearer " + accessToken )
127118 .characterEncoding ("UTF-8" )
128119 );
@@ -133,4 +124,314 @@ void uploadFile_fail_noFile() throws Exception {
133124 .andExpect (jsonPath ("$.message" ).value ("잘못된 요청입니다." ))
134125 .andDo (print ());
135126 }
127+
128+ @ Test
129+ @ DisplayName ("파일 조회 성공" )
130+ void readFile_success () throws Exception {
131+ // given
132+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
133+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
134+ user .setUserStatus (UserStatus .ACTIVE );
135+ userRepository .save (user );
136+
137+ String accessToken = generateAccessToken (user );
138+
139+ MockMultipartFile multipartFile = new MockMultipartFile (
140+ "multipartFile" ,
141+ "test.png" ,
142+ "image/png" ,
143+ "test" .getBytes ()
144+ );
145+
146+ FileUploadResponseDto fileUploadResponseDto = fileService .uploadFile (multipartFile , user .getId ());
147+
148+ // when
149+ ResultActions resultActions = mvc .perform (
150+ get ("/api/file/read/" + fileUploadResponseDto .getAttachmentId ())
151+ .header ("Authorization" , "Bearer " + accessToken )
152+ );
153+
154+ // then
155+ resultActions .andExpect (status ().isOk ())
156+ .andExpect (jsonPath ("$.code" ).value ("SUCCESS_200" ))
157+ .andExpect (jsonPath ("$.message" ).value ("파일 조회 성공" ))
158+ .andExpect (jsonPath ("$.data.publicURL" ).value (fileUploadResponseDto .getPublicURL ()))
159+ .andDo (print ());
160+
161+ }
162+
163+ @ Test
164+ @ DisplayName ("파일 조회 실패 - 없는 파일 정보 조회" )
165+ void readFile_failWhenFileNotFound () throws Exception {
166+ // given
167+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
168+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
169+ user .setUserStatus (UserStatus .ACTIVE );
170+ userRepository .save (user );
171+
172+ String accessToken = generateAccessToken (user );
173+
174+ Long attachmentId = 10000000L ;
175+
176+ // when
177+ ResultActions resultActions = mvc .perform (
178+ get ("/api/file/read/" + attachmentId )
179+ .header ("Authorization" , "Bearer " + accessToken )
180+ );
181+
182+ // then
183+ resultActions .andExpect (status ().isNotFound ())
184+ .andExpect (jsonPath ("$.code" ).value ("FILE_004" ))
185+ .andExpect (jsonPath ("$.message" ).value ("파일 정보를 찾을 수 없습니다." ))
186+ .andDo (print ());
187+ }
188+
189+ @ Test
190+ @ DisplayName ("파일 수정 성공" )
191+ void updateFile_success () throws Exception {
192+ // given
193+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
194+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
195+ user .setUserStatus (UserStatus .ACTIVE );
196+ userRepository .save (user );
197+
198+ String accessToken = generateAccessToken (user );
199+
200+ // 기존(삭제할) 파일 정보
201+ String path = "test.png" ;
202+ String contentType = "image/png" ;
203+ MockMultipartFile oldFile = new MockMultipartFile ("test" , path , contentType , "test" .getBytes ());
204+ FileUploadResponseDto fileUploadResponseDto = fileService .uploadFile (oldFile , user .getId ());
205+
206+ // 새 파일 정보
207+ String newPath = "newTest.png" ;
208+ MockMultipartFile newFile = new MockMultipartFile ("multipartFile" , newPath , contentType , "newTest" .getBytes ());
209+
210+ // when
211+ ResultActions resultActions = mvc .perform (
212+ multipart ("/api/file/update/" + fileUploadResponseDto .getAttachmentId ())
213+ .file (newFile ) // 파일 필드
214+ .header ("Authorization" , "Bearer " + accessToken )
215+ .characterEncoding ("UTF-8" )
216+ .with (request -> {
217+ request .setMethod ("PUT" );
218+ return request ;
219+ }) // PUT 매핑인 것을 나타낸다.
220+ );
221+
222+ // then
223+ resultActions .andExpect (status ().isOk ())
224+ .andExpect (jsonPath ("$.code" ).value ("SUCCESS_200" ))
225+ .andExpect (jsonPath ("$.message" ).value ("파일 업데이트 성공" ))
226+ .andExpect (jsonPath ("$.data.publicURL" , not (fileUploadResponseDto .getPublicURL ())))
227+ .andDo (print ());
228+ }
229+
230+ @ Test
231+ @ DisplayName ("파일 수정 실패 - 없는 아이디 조회" )
232+ void updateFile_failWhenFileNotFound () throws Exception {
233+ // given
234+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
235+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
236+ user .setUserStatus (UserStatus .ACTIVE );
237+ userRepository .save (user );
238+
239+ String accessToken = generateAccessToken (user );
240+
241+ // 새 파일 정보
242+ String newPath = "newTest.png" ;
243+ String contentType = "image/png" ;
244+ MockMultipartFile newFile = new MockMultipartFile ("multipartFile" , newPath , contentType , "newTest" .getBytes ());
245+
246+ Long attachmentId = 1000000L ;
247+
248+ // when
249+ ResultActions resultActions = mvc .perform (
250+ multipart ("/api/file/update/" + attachmentId )
251+ .file (newFile ) // 파일 필드
252+ .header ("Authorization" , "Bearer " + accessToken )
253+ .characterEncoding ("UTF-8" )
254+ .with (request -> {
255+ request .setMethod ("PUT" );
256+ return request ;
257+ }) // PUT 매핑인 것을 나타낸다.
258+ );
259+
260+ // then
261+ resultActions .andExpect (status ().isNotFound ())
262+ .andExpect (jsonPath ("$.code" ).value ("FILE_004" ))
263+ .andExpect (jsonPath ("$.message" ).value ("파일 정보를 찾을 수 없습니다." ))
264+ .andDo (print ());
265+ }
266+
267+ @ Test
268+ @ DisplayName ("파일 수정 실패 - 파일 입력이 없는 경우" )
269+ void updateFile_fail_noFile () throws Exception {
270+ // given
271+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
272+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
273+ user .setUserStatus (UserStatus .ACTIVE );
274+ userRepository .save (user );
275+
276+ String accessToken = generateAccessToken (user );
277+
278+ // 기존(삭제할) 파일 정보
279+ String path = "test.png" ;
280+ String contentType = "image/png" ;
281+ MockMultipartFile oldFile = new MockMultipartFile ("test" , path , contentType , "test" .getBytes ());
282+ FileUploadResponseDto fileUploadResponseDto = fileService .uploadFile (oldFile , user .getId ());
283+
284+ // when
285+ ResultActions resultActions = mvc .perform (
286+ multipart ("/api/file/update/" + fileUploadResponseDto .getAttachmentId ())
287+ .header ("Authorization" , "Bearer " + accessToken )
288+ .characterEncoding ("UTF-8" )
289+ .with (request -> {
290+ request .setMethod ("PUT" );
291+ return request ;
292+ }) // PUT 매핑인 것을 나타낸다.
293+ );
294+
295+ // then
296+ resultActions .andExpect (status ().isBadRequest ())
297+ .andExpect (jsonPath ("$.code" ).value ("COMMON_400" ))
298+ .andExpect (jsonPath ("$.message" ).value ("잘못된 요청입니다." ))
299+ .andDo (print ());
300+ }
301+
302+ @ Test
303+ @ DisplayName ("파일 수정 성공 - 파일 접근 권한 없음" )
304+ void updateFile_failWhenAccessDenied () throws Exception {
305+ // given
306+ User writer =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
307+ writer .setUserProfile (new UserProfile (writer , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
308+ writer .setUserStatus (UserStatus .ACTIVE );
309+ userRepository .save (writer );
310+
311+ User reader =
User .
createUser (
"reader" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
312+ reader .setUserProfile (new UserProfile (reader , "홍길순" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
313+ reader .setUserStatus (UserStatus .ACTIVE );
314+ userRepository .save (reader );
315+
316+ String accessToken = generateAccessToken (reader );
317+
318+ // 기존(삭제할) 파일 정보
319+ String path = "test.png" ;
320+ String contentType = "image/png" ;
321+ MockMultipartFile oldFile = new MockMultipartFile ("test" , path , contentType , "test" .getBytes ());
322+ FileUploadResponseDto fileUploadResponseDto = fileService .uploadFile (oldFile , writer .getId ());
323+
324+ // 새 파일 정보
325+ String newPath = "newTest.png" ;
326+ MockMultipartFile newFile = new MockMultipartFile ("multipartFile" , newPath , contentType , "newTest" .getBytes ());
327+
328+ // when
329+ ResultActions resultActions = mvc .perform (
330+ multipart ("/api/file/update/" + fileUploadResponseDto .getAttachmentId ())
331+ .file (newFile ) // 파일 필드
332+ .header ("Authorization" , "Bearer " + accessToken )
333+ .characterEncoding ("UTF-8" )
334+ .with (request -> {
335+ request .setMethod ("PUT" );
336+ return request ;
337+ }) // PUT 매핑인 것을 나타낸다.
338+ );
339+
340+ // then
341+ resultActions .andExpect (status ().isForbidden ())
342+ .andExpect (jsonPath ("$.code" ).value ("FILE_003" ))
343+ .andExpect (jsonPath ("$.message" ).value ("파일을 접근할 권한이 없습니다." ))
344+ .andDo (print ());
345+ }
346+
347+ @ Test
348+ @ DisplayName ("파일 삭제 성공" )
349+ void deleteFile_success () throws Exception {
350+ // given
351+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
352+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
353+ user .setUserStatus (UserStatus .ACTIVE );
354+ userRepository .save (user );
355+
356+ String accessToken = generateAccessToken (user );
357+
358+ // 기존(삭제할) 파일 정보
359+ String path = "test.png" ;
360+ String contentType = "image/png" ;
361+ MockMultipartFile oldFile = new MockMultipartFile ("test" , path , contentType , "test" .getBytes ());
362+ FileUploadResponseDto fileUploadResponseDto = fileService .uploadFile (oldFile , user .getId ());
363+
364+ // when
365+ ResultActions resultActions = mvc .perform (
366+ delete ("/api/file/delete/" + fileUploadResponseDto .getAttachmentId ())
367+ .header ("Authorization" , "Bearer " + accessToken )
368+ );
369+
370+ // then
371+ resultActions .andExpect (status ().isOk ())
372+ .andExpect (jsonPath ("$.code" ).value ("SUCCESS_200" ))
373+ .andExpect (jsonPath ("$.message" ).value ("파일 삭제 성공" ))
374+ .andDo (print ());
375+ }
376+
377+ @ Test
378+ @ DisplayName ("파일 삭제 실패 - 파일 접근 권한 없음" )
379+ void deleteFile_failWhenAccessDenied () throws Exception {
380+ // given
381+ User writer =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
382+ writer .setUserProfile (new UserProfile (writer , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
383+ writer .setUserStatus (UserStatus .ACTIVE );
384+ userRepository .save (writer );
385+
386+ User reader =
User .
createUser (
"reader" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
387+ reader .setUserProfile (new UserProfile (reader , "홍길순" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
388+ reader .setUserStatus (UserStatus .ACTIVE );
389+ userRepository .save (reader );
390+
391+ String accessToken = generateAccessToken (reader );
392+
393+ // 기존(삭제할) 파일 정보
394+ String path = "test.png" ;
395+ String contentType = "image/png" ;
396+ MockMultipartFile oldFile = new MockMultipartFile ("test" , path , contentType , "test" .getBytes ());
397+ FileUploadResponseDto fileUploadResponseDto = fileService .uploadFile (oldFile , writer .getId ());
398+
399+ // when
400+ ResultActions resultActions = mvc .perform (
401+ delete ("/api/file/delete/" + fileUploadResponseDto .getAttachmentId ())
402+ .header ("Authorization" , "Bearer " + accessToken )
403+ );
404+
405+ // then
406+ resultActions .andExpect (status ().isForbidden ())
407+ .andExpect (jsonPath ("$.code" ).value ("FILE_003" ))
408+ .andExpect (jsonPath ("$.message" ).value ("파일을 접근할 권한이 없습니다." ))
409+ .andDo (print ());
410+ }
411+
412+ @ Test
413+ @ DisplayName ("파일 삭제 실패 - 없는 파일 정보 조회" )
414+ void deleteFile_failWhenFileNotFound () throws Exception {
415+ // given
416+ User user =
User .
createUser (
"writer" ,
"[email protected] " ,
passwordEncoder .
encode (
"P@ssw0rd!" ));
417+ user .setUserProfile (new UserProfile (user , "홍길동" , null , "소개글" , LocalDate .of (2000 , 1 , 1 ), 1000 ));
418+ user .setUserStatus (UserStatus .ACTIVE );
419+ userRepository .save (user );
420+
421+ String accessToken = generateAccessToken (user );
422+
423+ Long attachmentId = 1000000L ;
424+
425+ // when
426+ ResultActions resultActions = mvc .perform (
427+ delete ("/api/file/delete/" + attachmentId )
428+ .header ("Authorization" , "Bearer " + accessToken )
429+ );
430+
431+ // then
432+ resultActions .andExpect (status ().isNotFound ())
433+ .andExpect (jsonPath ("$.code" ).value ("FILE_004" ))
434+ .andExpect (jsonPath ("$.message" ).value ("파일 정보를 찾을 수 없습니다." ))
435+ .andDo (print ());
436+ }
136437}
0 commit comments