카테고리 없음

multiparit/form-data폼데이터로 json을 보내는 경우 테스트 하는 방법(postman, swagger, mocktest)

Lahezy 2023. 8. 22.
728x90

스웨거 테스트를 진행하면서 mutlipart formdata를 사용할 때 사진 파일과 json파일은 동시에 보내는 경우를 어떻게 테스트하는지 알아봤습니다. 

 

1. 포스트맨 

포스트맨 에서 테스트 하는 경우는 Formdata와 함께 json 파일을 보내는 경우 content type을 지정해서 전송할 수 있습니다.

아래와 같이 전송됩니다.

 

 

2.swagger

해당 부분을 swagger로 해결하는 방법은 두 가지가 있습니다.

1. file로 받는 방법

@Operation(summary = "피드 작성")
@PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ApiResponse<PostResponseDto> savePostWithImage(
        @Valid @RequestPart(value = "postRequestDto") @Parameter(schema = @Schema(type = "string", format = ("binary"))) PostRequestDto postRequestDto,
        @RequestPart(name = "files", required = false) @Parameter(description = "포스트 이미지") List<MultipartFile> files,
        @RequestPart(name = "file", required = false) @Parameter(description = "포스트 썸네일 이미지 등록하지 않는 경우 자동으로 처음이미지 설정") MultipartFile file
) {
    PostResponseDto postResponseDto = postService.saveWithImages(postRequestDto, files, file, getCurrentUsername());
    return ApiResponse.success(postResponseDto);
}

위에 처럼 코드를 작성하여 json부분을 파일로 넣는 방법입니다.

 

 

위와 같이 전송하면 아래와 같이 잘 전송된것을 확인할 수 있습니다.

 

2. 처리하는 bean 을 추가하는 방법(octetstream 허용)

SwaggerBeanConfig를 추가합니다.

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.util.ArrayList;

@Configuration
public class SwaggerBeanConfig {
    
    public SwaggerBeanConfig(MappingJackson2HttpMessageConverter converter) {
        var supportedMediaTypes = new ArrayList<>(converter.getSupportedMediaTypes());
        supportedMediaTypes.add(new MediaType("application", "octet-stream"));
        converter.setSupportedMediaTypes(supportedMediaTypes);
    }
}

json으로 전송하지 않는 경우 아래와 같은 오류가 발생하는데 octet-stream을 받을 수 있도록 해줍니다.

Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/octet-stream' is not supported]

이후에 컨트롤러에서는 동일하게 @RequestPart를 이용하여 입력을 받습니다.

@Operation(summary = "피드 작성")
@PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ApiResponse<PostResponseDto> savePostWithImage(
        @Valid @RequestPart(name="postRequestDto") PostRequestDto postRequestDto,
        @RequestPart(name = "files", required = false) @Parameter(description = "포스트 이미지") List<MultipartFile> files,
        @RequestPart(name = "file", required = false) @Parameter(description = "포스트 썸네일 이미지 등록하지 않는 경우 자동으로 처음이미지 설정") MultipartFile file
) {
    PostResponseDto postResponseDto = postService.saveWithImages(postRequestDto, files, file, getCurrentUsername());
    return ApiResponse.success(postResponseDto);
}

 

위와 모두 requestPart로 입력을 동일하게 받습니다. 

위와 같이 잘 입력받아 저장되는것을 확인할 수 있습니다.

 

 

3. test코드

또한 참고로 만약 테스트 코드를 작성하는 경우라면 위와 같은 예제는 아니지만 아래와 같이 오브젝트를 json파일로 변환해서 보내줄 수 있습니다.

@Test
@DisplayName("item 생성 조회 (POST /items)")
public void saveItem() throws Exception {
    //given
    RequestSalesItemDto dto = getRequestSalesItemDto();
    String requestSalesItemDto = new ObjectMapper().writeValueAsString(dto);

    //when
    //아래와 같이 json으로 변환해서 보내준다
    MockMultipartFile jsonFile = new MockMultipartFile("requestSalesItemDto", "requestSalesItemDto", "application/json", requestSalesItemDto.getBytes(StandardCharsets.UTF_8));
    mockMvc.perform(multipart("/items")
                    .file(jsonFile)
                    .header("Authorization", loginDto.getGrantType() + " " + loginDto.getAccessToken()))

            .andExpectAll(
                    status().is2xxSuccessful(),
                    jsonPath("message").value(SAVE_ITEM_MESSAGE),
                    content().contentType(MediaType.APPLICATION_JSON)
            );

    //then
    List<SalesItem> all = salesItemRepository.findAll();
    SalesItem salesItem = all.get(0);
    assertThat(salesItem.getTitle()).isEqualTo(dto.getTitle());
    }

 

 

참고

https://velog.io/@dhk22/Spring-MultipartFile%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-MultipartFile%EA%B3%BC-%ED%95%A8%EA%BB%98-%EC%A0%84%EC%86%A1%EB%90%98%EB%8A%94-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EA%B0%9D%EC%B2%B4%EB%A1%9C-%EB%B0%9B%EA%B3%A0-%EC%8B%B6%EC%9D%8C

https://swagger.io/docs/specification/describing-request-body/multipart-requests/

https://github.com/swagger-api/swagger-ui/issues/6462

https://github.com/swagger-api/swagger-ui/issues/5169

https://github.com/Morasiu/Swashbuckle.AspNetCore.JsonMultipartFormDataSupport

https://whatsmyinterest.tistory.com/76

https://stackoverflow.com/questions/16230291/requestpart-with-mixed-multipart-request-spring-mvc-3-2

https://github.com/springdoc/springdoc-openapi/issues/820

https://github.com/springdoc/springdoc-openapi/issues/833

https://github.com/springdoc/springdoc-openapi/issues/396

https://minholee93.tistory.com/entry/Spring-Json-with-MultipartFile

출처: 스웨거의 깃허브 이슈

 

728x90

댓글