-
[스프링부트] 이미지 업로드 테스트 postman + restdocsBackEnd/SpringBoot 2023. 12. 3. 19:44
1. RequestPart
Content-Type이 multipart/form-data로 오는 요청에 대해 동작하며
MultipartResolver 를 통해서 multipartFile을 받을 수있고 동시에 HttpMessageConverter를 통해서 RequestBody도 수행함을 알 수있다.
공식문서 :
RequestPart (Spring Framework 6.1.1 API)
Annotation that can be used to associate the part of a "multipart/form-data" request with a method argument. Supported method argument types include MultipartFile in conjunction with Spring's MultipartResolver abstraction, jakarta.servlet.http.Part in conj
docs.spring.io
2. 테스트 대상 컨트롤러
multipartFile : thumbnailImg, roomImgList
requestbody : appRoomView
@LoginCompanyCheck@PostMapping("/create")public JsonResponse<AppRoomDTO> appCompanyCreate(@CurrentCompany LoginCompanyInfo loginCompanyInfo,@RequestPart(value = "appRoomView") AppRoomView appRoomView,@RequestPart(value = "thumbnailImg", required = false) MultipartFile thumbnailImg,@RequestPart(value = "roomImgList", required = false) List<MultipartFile> roomImgList)throws UserNotFoundException {AppRoomDTO appRoomDTO = appRoomService.companyRoomCreate(loginCompanyInfo, appRoomView, thumbnailImg, roomImgList);return JsonResponse.success(appRoomDTO);}3. Postman
3.1 Body
json 객체의 경우 다음과같이 작성한다.
key : controller key와 동일하게 설정
value : json 필드 동일하게 설정
content-Type : application/json 입력
Postman Body key : controller key와 동일하게 설정 ( file로 설정 )
value : selectFiles눌러서 선택 (List 타입인경우 여러개 클릭후 선택)
content-Type : multipart/form-data 입력
Postman Body file 옆칸에 working directory 경고가 뜬다면 설정 -> Read files outside working directory를 On 해준다.
Postman Body 3.1 Header
header는 자동으로 body에 형식으로 잡히기 때문에 그대로 진행한다.
만약에 Content-Type에서 multipart/form-data;로 수정하는경우 boundary 에러가 발생한다.
boundary를 자동으로 계산할수있게 기본 설정으로 둔다.
Postman Header 4. Spring-rest-docs
MockMultiPartFile을 생성한다.
이미지 데이터
MockMultipartFile thumbNailImg = new MockMultipartFile("thumbNailImg", "image.png", MediaType.MULTIPART_FORM_DATA_VALUE, "example".getBytes());Json 데이터
String requestJson = objectMapper.writeValueAsString(new AppRoomView("roomNm","comName",1,LocalDateTime.now(),LocalDateTime.now(),"roomDesc","Y",5));MockMultipartFile requestBody = new MockMultipartFile("appRoomView", "", MediaType.APPLICATION_JSON_VALUE, requestJson.getBytes());mockMvc
방금 생성한 mock파일을 넣어준다.
mockMvc.perform(multipart("/room/create").file(thumbNailImg).file(requestBody)전체 코드
@Test@DisplayName("객실 정보 수정")@WithMockCustomUserpublic void roomModifyTest() throws Exception {// givenString requestJson = objectMapper.writeValueAsString(new AppRoomView("roomNm","comName",1,LocalDateTime.now(),LocalDateTime.now(),"roomDesc","Y",5));List<MockMultipartFile> roomPicList = new ArrayList<>();for (int i = 0; i < 2; i++) {roomPicList.add(new MockMultipartFile("roomImgList", i + "image.png", MediaType.MULTIPART_FORM_DATA_VALUE, "example".getBytes()));}MockMultipartFile thumbNailImg = new MockMultipartFile("thumbNailImg", "image.png", MediaType.MULTIPART_FORM_DATA_VALUE, "example".getBytes());MockMultipartFile requestBody = new MockMultipartFile("appRoomView", "",MediaType.APPLICATION_JSON_VALUE, requestJson.getBytes());given(appRoomService.companyRoomCreate(any(LoginCompanyInfo.class), any(AppRoomView.class), any(MultipartFile.class), any(List.class))).willReturn(AppRoomDTO.builder().id(1L).comId(1L).comName("toryCompany").soldOutYn("N").couponYn("Y").thumbNail("defaultThumbNail").roomDesc("roomDesc").maxCount(1).sellPrc(100000).roomPicDTOList(List.of(AppRoomPicDTO.builder().id(1L).picLocation("UUID + pictureImgName").picSeq(0).modifiedDate(LocalDateTime.now()).createdDate(LocalDateTime.now()).build())).modifiedDate(LocalDateTime.now()).createdDate(LocalDateTime.now()).build());// whenmockMvc.perform(multipart("/room/create").file(roomPicList.get(0)).file(roomPicList.get(1)).file(thumbNailImg).file(requestBody).cookie(new Cookie(CommonConstant.ACCOUNT_TOKEN.getName(), "jwtToken")).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))// then.andExpect(status().isOk()).andDo(restDocs.document(requestCookies(cookieWithName(CommonConstant.ACCOUNT_TOKEN.getName()).description("JWT 토큰")),requestParts(partWithName("thumbNailImg").description("객실 썸네일 파일").optional(),partWithName("roomImgList").description("객실 이미지 파일들").optional(),partWithName("appRoomView").description("객실 정보 수정")),requestPartFields("appRoomView",fieldWithPath("roomNm").type(JsonFieldType.STRING).description("객실 이름"),fieldWithPath("comName").type(JsonFieldType.STRING).description("회사 이름"),fieldWithPath("sellPrc").type(JsonFieldType.NUMBER).description("객실 가격"),fieldWithPath("checkIn").type(JsonFieldType.STRING).description("체크 인 시간"),fieldWithPath("checkOut").type(JsonFieldType.STRING).description("체크 아웃 시간"),fieldWithPath("roomDesc").type(JsonFieldType.STRING).description("객실 설명"),fieldWithPath("couponYn").type(JsonFieldType.STRING).description("쿠폰 사용 여부"),fieldWithPath("maxCount").type(JsonFieldType.NUMBER).description("총 객실 수")),responseFields(fieldWithPath("message").type(JsonFieldType.STRING).description("메세지"),fieldWithPath("result").type(JsonFieldType.STRING).description("결과"),fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터"),fieldWithPath("data.id").type(JsonFieldType.NUMBER).description("객실 ID"),fieldWithPath("data.comId").type(JsonFieldType.NUMBER).description("기업 ID"),fieldWithPath("data.comName").type(JsonFieldType.STRING).description("기업 명"),fieldWithPath("data.soldOutYn").type(JsonFieldType.STRING).description("품절 여부"),fieldWithPath("data.thumbNail").type(JsonFieldType.STRING).description("객실 썸네일 이미지"),fieldWithPath("data.roomDesc").type(JsonFieldType.STRING).description("객실 설명"),fieldWithPath("data.maxCount").type(JsonFieldType.NUMBER).description("총 객실 수"),fieldWithPath("data.roomDesc").type(JsonFieldType.STRING).description("객실 설명"),fieldWithPath("data.sellPrc").type(JsonFieldType.NUMBER).description("객실 가격"),fieldWithPath("data.couponYn").type(JsonFieldType.STRING).description("쿠폰 사용 여부"),fieldWithPath("data.roomPicDTOList").type(JsonFieldType.ARRAY).description("객실 사진 정보"),fieldWithPath("data.roomPicDTOList[].id").type(JsonFieldType.NUMBER).description("객실 사진 ID"),fieldWithPath("data.roomPicDTOList[].picLocation").type(JsonFieldType.STRING).description("객실 사진 위치 명"),fieldWithPath("data.roomPicDTOList[].picSeq").type(JsonFieldType.NUMBER).description("객실 사진 순서"),fieldWithPath("data.roomPicDTOList[].modifiedDate").type(JsonFieldType.STRING).description("객실 사진 생성 일시"),fieldWithPath("data.roomPicDTOList[].createdDate").type(JsonFieldType.STRING).description("객실 사진 수정 일시"),fieldWithPath("data.modifiedDate").type(JsonFieldType.STRING).description("객실 생성 일시"),fieldWithPath("data.createdDate").type(JsonFieldType.STRING).description("객실 수정 일시"))));}완성된 request 필드
'BackEnd > SpringBoot' 카테고리의 다른 글
[스프링부트] @DataJpaTest 멀티스레드에서 no value present (1) 2023.12.06 [스프링부트] 테스트 시 Mysql관련 에러 Unique index or primary key violation (0) 2023.11.24 [스프링부트] ./gradlew build시 에러 -> error: cannot find symbol (0) 2023.11.16 토비의 스프링 - 1권 6장 AOP (0) 2023.10.08