Framework/Spring

[SpringBoot] MockMvc로 Multipart() 테스트 코드 작성하기

jyjyjy25 2024. 2. 15. 01:10

MockMvc를 이용하여 Controller 테스트 코드를 작성한다.

테스트할 코드는 form-data 형식으로 이미지 파일과 텍스트를 입력 받아 유저 리소스를 수정하는 PATCH 메서드이다.

 

1. MockMultipartFile 객체 생성

MockMultipartFile file = new MockMultipartFile(
            "홍길동전 썸네일 이미지",
            "thumbnail.png",
            MediaType.IMAGE_PNG_VALUE,
            "thumbnail".getBytes()
        );

MockMulipartFile은 MultipartFile 인터페이스를 상속 받는 가짜 객체다.

multipart 파일을 업로드하는 컨트롤러 테스트에 사용된다.

 

2. 요청

mockMvc.perform(
    multipart(HttpMethod.PATCH, BASE_URL + "/profile")
        .file(file)
        .param("nickName", nickname)
        .with(csrf()));

- perform.patch()가 아닌 perform(multipart())로 요청한다.

 

- HttpMethod.PATCH를 입력 매개변수의 첫 번째 위치에 넣어준다.

multipart()는 기본적으로 POST로 하드 코딩되어 있다. 하지만 내부 코드에 Http Method를 매개변수로 받을 수 있도록 오버 로딩되어 있다.

 

- CSRF 토큰에 대한 문제로 발생하므로 .with(csrf())를 추가한다.

받은 요청에 CSRF 토큰이 담겨있지 않아 세션에 저장된 CSRF 값과 비교할 수 없어 403 Forbidden 에러가 발생하게 된다.

 

✏️ CSRF(Cross-Site-Request Forgery)란?
악의적인 코드를 심어놓은 사이트에서 로그인한 사용자가 클릭하게 하여 사용자의 의지와 무관한 요청을 발생시키는 공격을 의미한다.
Spring Security에서는 이를 방지하기 위해 "CSRF Token"을 이용해 토큰을 비교한 뒤 일치하는 경우에만 메서드를 정상적으로 실행하게 만든다.
참고로 RESTFul한 웹 서비스에서는 대부분 비활성화로 설정한다고 한다.
REST API는 대부분 무상태성을 유지하며, JWT와 같은 토큰 방식으로 인증하기 때문에 요청이 세션에 의존하지 않기 때문이다.

 

3. 전체 코드

@Test
@DisplayName("유저는 자신의 프로필을 수정할 수 있다.")
public void updateUserProfile() throws Exception {
    // given
    String nickname = "닉네임1";
    MockMultipartFile file = new MockMultipartFile(
        "홍길동전 썸네일 이미지",
        "thumbnail.png",
        MediaType.IMAGE_PNG_VALUE,
        "thumbnail".getBytes()
    );

    // when
    ResultActions result =
        mockMvc.perform(
            multipart(HttpMethod.PATCH, BASE_URL + "/profile")
                .file(file)
                .param("nickName", nickname)
                .with(csrf()));

    // then
    result.andExpect(status().isOk())
        .andExpect(jsonPath("$.data").isNotEmpty())
        .andExpect(jsonPath("$.data", "성공적으로 프로필이 업데이트 되었습니다.").exists());
}

 

Reference

 

[SpringBoot] MockMvc - multipart() POST외 다른 HTTPMethod 사용하기

개발 환경 Build : Gradle SpringBoot : 2.7.5 Java : 11 OS : Mac 요구사항 RestDocs API 문서화를 위해 MockMvc를 이용하여 Controller 테스트 코드를 작성해야 함. 테스트할 코드는 form-data로 이미지 파일과 텍스트를

wonkang.tistory.com

 

[TroubleShooting] SpringBoot Controller Test - MockMvc 302 Found, 403 Forbidden

개발 환경 Build : Gradle SpringBoot : 2.7.5 Java : 11 OS : Mac 발생 - 403 Forbidden RestDocs를 사용하여 API 문서화 작업을 하려고 Controller에서 테스트 코드를 작성 후 테스트를 진행하였고, 403 Forbidden 에러가 발

wonkang.tistory.com