본문 바로가기
카테고리 없음

[ Backend / Java / SpringBoot ] multipartFile을 다른 속성값과 객체에 넣어 전달받을때 + 테스트 코드 짜는 법 2

by 날파리1 2022. 12. 27.

1. 컨트롤러 코드

  1. 멀티 파일과 객체를 같이 받아오는 것은 RequestBody가 아니라 RequestPart로 받아와야함.
  2. PostMapping 에서 value와 consumes 을 써준 후 뒤에 타입을 아래와 같이 밝혀줘야함.
  3. value 는 URI 주소 consumes 는 타입
  4. RequestPart 뒤의 value 값은 받아오는 객체의 이름과 파일이름과 반드시 일치해야함. 그렇지 않으면 찾는 값이 null 이라고 400 오류가 뜸.
@PostMapping(value = "/practicalTemplate",consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
@ResponseStatus(HttpStatus.CREATED)
public PracticalTemplateDto createNewPracticalTemplate(
    @RequestPart(value = "practicalTemplate") PracticalTemplateRegistrationDto practicalTemplateRegistrationDto,
    @RequestPart(value="multipartFile", required = false) MultipartFile multipartFile
  ) throws IOException {

      return createPracticalTemplateService.practicalTemplate(practicalTemplateRegistrationDto,multipartFile);
  }

2. <Spring Boot> content type 'application/octet-stream' not supported 415 오류 해결

1번 처럼 해도 415번 오류가 뜸.

클래스를 하나 만들어서(난 util이라고 만들었음) 아래와 같이 복붙

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;

@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {

    /**
     * Converter for support http request with header Content-Type: multipart/form-data
     */
    public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper, MediaType.APPLICATION_OCTET_STREAM);
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return false;
    }

    @Override
    public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
        return false;
    }

    @Override
    protected boolean canWrite(MediaType mediaType) {
        return false;
    }
}

그럼 해결~

 

<Spring Boot> content type 'application/octet-stream' not supported 오류 해결

@RequestPart과 MultipartFile을 사용하여 이미지 올리는 것을 구현하는 중 content type 'application/octet-stream' not supported ~. 오류가 발생하였다.\-> MultipartJackson2HttpMessag

velog.io

 

 

@RequestPart with mixed multipart request, Spring MVC 3.2

I'm developing a RESTful service based on Spring 3.2. I'm facing a problem with a controller handling mixed multipart HTTP request, with a Second part with XMLor JSON formatted data and a second part

stackoverflow.com

 

3. multipartFile 과 requestPart 테스트 코드 짜는 법

당연히 위와 같이 하면 테스트 코드가 터진다...

multipartFile을 mocking해주자

@Test
  void create() throws Exception {

    MockMultipartFile multipartFile = new MockMultipartFile("multipartFile", "filename.mp4", "video/mp4", "some xml".getBytes());
    MockMultipartFile jsonFile = new MockMultipartFile("practice", "", "application/json",
        ("{" +
            "\"title\":\"바에서 음료 물어보기\"," +
            "\"situation\":\"바에서 말 걸때\"," +
            "\"koreanScript\":\"어떤 음료 좋아하세요?\"," +
            "\"englishScript\":\"what kind of drink do you like?\"" +
            "}").getBytes());

    given(createPracticeService.practice(any(),any(),any())).willReturn(
        Practice.fake().toDto()
    );

    mockMvc.perform(MockMvcRequestBuilders.multipart("/practice/new")
            .file(multipartFile)
            .file(jsonFile)
            .requestAttr("userId",1L))
        .andExpect(status().isCreated())
        .andExpect(content().string(containsString("카페에서 지갑 잃어버렸을때")));

  }
}

3. S3 테스트 코드 짜는 법

S3 는 서비스 로직이나 이용해주는 로직에서 mock 만 해주면 된다.

class ClassName {
  private S3Uploader s3Uploader;

 @BeforeEach
 void setUp() {
    s3Uploader = mock(S3Uploader.class);
  }

 

예시 코드

class CreatePracticeServiceTest {
  private PracticeRepository practiceRepository;
  private S3Uploader s3Uploader;
  private CreatePracticeService createPracticeService;

  @BeforeEach
  void setUp() {
    practiceRepository = mock(PracticeRepository.class);
    s3Uploader = mock(S3Uploader.class);
    createPracticeService = new CreatePracticeService(practiceRepository,s3Uploader);
  }

  @Test
  void createPractice() throws IOException {
    given(practiceRepository.save(any())).willReturn(Practice.fake());

    MockMultipartFile mockMultipartFile = new MockMultipartFile("multipartFile","filename.txt", "text/plain", "some xml".getBytes());

    createPracticeService.practice(1L, PracticeRegistrationDto.fake(),mockMultipartFile);

    verify(practiceRepository).save(any());
  }
}

댓글