본문 바로가기

오류일기

[Spring Boot] MockMvc를 이용해 파일과 제이슨 형태를 한번에 받는 메소드 테스트하기

이러저러한 이유로 근 반년만에 프로젝트를 진행하게 되었습니다. 덕분에 모든것이 새로웠습니다. ㅎ..

프로젝트 시작할 때의 저입니다.

저는 멀티파트로 이미지 파일과 Json을 한번에 받아서 처리해야 하는 로직을 작성해야 했습니다. 과거의 저였다면 @RestController로 슥슥 동작하는지만 확인하고 바로 다음 로직을 구현하는데 집중하였을 것입니다. 그러나 최근 "클린코드"를 읽었고 "객체지향의 사실과 오해", "오브젝트"라는 책을 읽고 있기에 이 참에 TDD를 통해 구현해보고자 마음먹었습니다.

비록...구현을 먼저하고 이에 대한 테스트 코드를 작성하였으니 올바른 TDD는 아니지만... 그래도...

 

그렇게 구글링을 하며 MockMvc를 통해 이미지 파일 전송에 대한 테스트 까지는 어찌저찌 하였고 그 결과 아래와 같은 코드를 작성하였습니다.

@AutoConfigureMockMvc
@SpringBootTest
class ReportsControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Test
    @DisplayName("파일과 함께 신고에 대한 정보를 받아들였을때 신고가 성공적으로 이루어지는지 확인")
    void 신고하기_정상시나리오() throws Exception {
        //given
        MockMultipartFile file = new MockMultipartFile(
                "imgFiles",
                "testImage.png",
                MediaType.IMAGE_PNG_VALUE,
                new FileInputStream("src/test/resources/testImage/testImage.png"));

        ReportRequestDto testDescription = new ReportRequestDto(37.123456, 127.123456, "testDescription", 1, 1);

        //when
        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

        //then
        mockMvc.perform(multipart("/reports")
                        .file(file)
                        .content(new ObjectMapper().writeValueAsString(testDescription))
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }

}

 

그리고 이에 대한 실행 결과는...

 

400에러가 뜨면서 requestDto를 찾을 수 없다는 에러였습니다.

 

파일 전송에 대한 내용을 잘 모르기에 일반적인 테스트를 하듯 content로 제이슨 형식으로 보낸것이 원인이였습니다.

정확한 내용은 모르지만 포스트맨으로 multipart로 요청을 보낼때 단순히 body에 값을 넣어 보내는 것이 아닌 다음과 같이 보냈는 것을 참고하여 코드를 수정하였습니다.

키와 밸류, 즉 일반적인 제이슨과는 다른 방식으로 보내면 되지 않을까 하고 시도해보았습니다.

 

아래는 수정한 코드입니다.

@AutoConfigureMockMvc
@SpringBootTest
class ReportsControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Test
    @DisplayName("파일과 함께 신고에 대한 정보를 받아들였을때 신고가 성공적으로 이루어지는지 확인")
    void 신고하기_정상시나리오() throws Exception {
        //given
        ReportRequestDto testDescription = new ReportRequestDto(37.123456, 127.123456, "testDescription", 1, 1);

        MockMultipartFile imgFiles = new MockMultipartFile(
                "imgFiles",
                "testImage.png",
                MediaType.IMAGE_PNG_VALUE,
                new FileInputStream("src/test/resources/testImage/testImage.png"));

        MockMultipartFile requestDto = new MockMultipartFile("requestDto", "", "application/json",
                new ObjectMapper().writeValueAsString(testDescription).getBytes());

        //when
        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

        //then
        mockMvc.perform(multipart("/reports")
                        .file(imgFiles)
                        .file(requestDto))
                .andExpect(status().isOk());
    }

}

즉 객체에 파일 취급하여 전송하면...

다음과 같은 초록창이 나오게 됩니다...!