[Spring] MockMvc @RequestPart MultipartFile 테스트 405 에러 해결

Walter Mitty·2023년 6월 15일
0

Controller

@PutMapping(value = "/modify",  name = "자주묻는질문 > 수정")
    public BaseResponse<String> faqModify(@Valid @RequestPart FaqRegistRequest request, @RequestPart(required = false) List<MultipartFile> files) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        faqApplicationService.modifyFaqInfo(request, files);
        return BaseResponse.ofSuccess("자주묻는질문 수정 완료");
    }

먼저 Controller 단을 보면 @RequestPart로 Request 객체와, MultipartFile들을 받고 있다.
이때 나는 수정 로직을 하고있었어서 @PutMapping 으로 지정해놨는데, 자꾸 맞지 않는 HttpMethod로 요청을 보냈을 때 발생하는 405 에러가 발생했다.

그냥 multipart()로 보내주고 있었는데, Multipart/form-data 요청은 default가 POST 였다.

따라서, 코드에서 HttpMethod 설정해줘야한다.

기존 에러 코드

Test Controller

    @Test
    void 자주묻는질문_수정() throws Exception {
        doNothing().when(faqApplicationService).modifyFaqInfo(any(FaqRegistRequest.class), anyList());

        String accessToken = "access_token";
        String result = "자주묻는질문 수정 완료";

        List<Integer> deleteFaqImageIds = new ArrayList<>();
        deleteFaqImageIds.add(1);
        deleteFaqImageIds.add(2);
        deleteFaqImageIds.add(5);

        FaqRegistRequest faqRequest = FaqRegistRequest.builder()
            .faqTitle("치실, 치간칫솔, 칫솔질 중 어떤 것을 먼저 해야 되나요?")
            .faqContent("순서는 상관 없고 선호하는대로 하면 됩니다.")
            .faqId(1)
            .deleteFaqImageIds(deleteFaqImageIds)
            .build();

        MockMultipartFile file = new MockMultipartFile("files", "tooth.png", "multipart/form-data", "uploadFile".getBytes(StandardCharsets.UTF_8));
        MockMultipartFile request = new MockMultipartFile("request", null, "application/json", objectMapper.writeValueAsString(faqRequest).getBytes(StandardCharsets.UTF_8));

        mockMvc.perform(
                multipart("/faq/modify")
                    .file(file)
                    .file(request)
                    .contentType(MediaType.MULTIPART_FORM_DATA)
                    .accept(MediaType.APPLICATION_JSON)
                    .header("Authorization", accessToken)
            )
            .andExpect(status().isOk())
            .andExpect(jsonPath("code").value(200))
          .andExpect(jsonPath("message").value(SuccessMessage.SUCCESS_MSG))
            .andExpect(jsonPath("data").value(result))
            .andDo(document("faq/modify",
                getDocumentRequest(),
                getDocumentResponse(),
                requestParts(
                    partWithName("request").description("요청값 Json"),
                    partWithName("files").description("업로드 파일").optional()
                ),
                responseFields(
                    fieldWithPath("code").type(JsonFieldType.NUMBER).description("결과 코드"),
                    fieldWithPath("message").type(JsonFieldType.STRING).description("결과 메시지"),
                    fieldWithPath("data").type(JsonFieldType.STRING).description("결과 데이터")
                )
            ));

        verify(faqApplicationService).saveFaq(any(FaqRegistRequest.class), anyList());
    }

성공 코드

Test Controller

@Test
    void 자주묻는질문_수정() throws Exception {
       doNothing().when(faqApplicationService).modifyFaqInfo(any(FaqRegistRequest.class), anyList());

        String accessToken = "access_token";
        String result = "자주묻는질문 수정 완료";

        List<Integer> deleteFaqImageIds = new ArrayList<>();
        deleteFaqImageIds.add(1);
        deleteFaqImageIds.add(2);
        deleteFaqImageIds.add(5);

        FaqRegistRequest faqRequest = FaqRegistRequest.builder()
            .faqTitle("치실, 치간칫솔, 칫솔질 중 어떤 것을 먼저 해야 되나요?")
            .faqContent("순서는 상관 없고 선호하는대로 하면 됩니다.")
            .faqId(1)
            .deleteFaqImageIds(deleteFaqImageIds)
            .build();

        MockMultipartFile file = new MockMultipartFile("files", "tooth.png", "multipart/form-data", "uploadFile".getBytes(StandardCharsets.UTF_8));
        MockMultipartFile request = new MockMultipartFile("request", null, "application/json", objectMapper.writeValueAsString(faqRequest).getBytes(StandardCharsets.UTF_8));

        mockMvc.perform(MockMvcRequestBuilders  //<------ 요기!!!
                .multipart(HttpMethod.PUT, "/faq/modify") //<-------- 요기!!!
                    .file(file)
                    .file(request)
                    .accept(MediaType.APPLICATION_JSON)
                    .contentType(MediaType.MULTIPART_FORM_DATA)
                    .header("Authorization", accessToken)
            )
            .andExpect(status().isOk())
            .andExpect(jsonPath("code").value(200))
            .andExpect(jsonPath("message").value(SuccessMessage.SUCCESS_MSG))
            .andExpect(jsonPath("data").value(result))
            .andDo(document("faq/modify",
                getDocumentRequest(),
                getDocumentResponse(),
                requestParts(
                    partWithName("request").description("요청값 Json"),
                    partWithName("files").description("업로드 파일").optional()
                ),
                responseFields(
                    fieldWithPath("code").type(JsonFieldType.NUMBER).description("결과 코드"),
                    fieldWithPath("message").type(JsonFieldType.STRING).description("결과 메시지"),
                    fieldWithPath("data").type(JsonFieldType.STRING).description("결과 데이터")
                )
            ));
        verify(faqApplicationService).modifyFaqInfo(any(FaqRegistRequest.class), anyList());
    }

포인트는, MockMvcRequestBuilders을 이용하여 Reuqest를 한번 빌드를 해줘야한다. 그러면 추가로 HttpMethod.PUT을 명시해줄 수 있다.

0개의 댓글