게시글에 이미지를 첨부하여 작성하는 기능을 구현하고자 Controller에서 @RequestBody
로 Dto를 받고, @RequestPart
로 이미지 파일을 받고자 하는 상황이었다. Postman에서 해당 API를 테스트하는데 다음과 같은 오류가 발생하였다.
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain;charset=UTF-8' not supported
이 경우, dto와 file 모두 @RequestPart
로 받고, 해당 애노테이션에서 value값을 정확하게 지정해야 한다.
애노테이션 value값을 지정하지 않았을 경우 컨트롤러가 다음과 같이 읽지 못하는 경우가 발생한다.
Required request part 'dto' is not present
코드를 수정하면 다음과 같다.
@PostMapping("/boards")
public ResponseEntity<ResultResponse> enroll(@RequestPart(value = "dto") EnrollRequest dto,
@RequestPart(value = "files") List<MultipartFile> files,
@AuthenticationPrincipal AuthMember authMember) {
BoardResponse responseDto = boardService.create(dto, files, authMember);
ResultResponse result = ResultResponse.of(ResultCode.ENROLL_SUCCESS, responseDto);
return new ResponseEntity<>(result, HttpStatus.valueOf(result.getStatus()));
}
이 후 Postman에서 form-data로 다음과 같이 지정하여 요청하면 정상적으로 API 응답 결과가 반환된다. (세부적인 사항도 정확하게 지정해야 한다.)
// 임시적으로 file을 실제 파일명과 서버에 저장하는 파일명을 구분하지 않고 지정한 상태다.
@Test
@DisplayName("게시글 등록 성공")
@WithMockAuthUser(id = 1L, email = "test@test.com", role = Role.ROLE_ADMIN)
void postSuccess() throws Exception {
//given
Map<String, String> input = new HashMap<>();
input.put("title", "게시글 제목 테스트");
input.put("contents", "게시글 본문 테스트");
BoardResponse board = givenBoard();
MockMultipartFile files = new MockMultipartFile(
"files",
"imagefile.png",
"image/png",
"<<png data>>".getBytes());
String contents = mapper.writeValueAsString(input);
given(boardService.create(any(EnrollRequest.class), anyList(), any(AuthMember.class))).willReturn(board);
//andExpect
mockMvc.perform(
multipart("/boards")
.file(files)
.file(new MockMultipartFile("dto", "", "application/json", contents.getBytes(StandardCharsets.UTF_8)))
.contentType("multipart/form-data")
.accept(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8"))
.andExpect(status().is2xxSuccessful())
.andDo(print());
}
WebMvcTest를 통해 해당 메소드를 단위 테스트하는 과정에서 다음과 같은 오류가 있었지만, 위 코드와 같이 해결하였다.
Content type 'application/octet-stream' not supported
테스트 결과 모두 성공하였다.