TIL

24.01.12) TIL

oneseel 2024. 1. 13. 12:03

@RequestPart 사용할 때, 컨트롤러 테스트 작성은 어떻게 해야할까?

// 게시글 작성
@PostMapping
public ResponseEntity<?> createPost(
    @RequestPart(value = "requestDto") PostRequestDto requestDto,
    @RequestPart(value = "file", required = false) MultipartFile file,
    @RequestParam(required = false) GameType gameType,
    @RequestParam(required = false) GameName gameName,
    @RequestParam BoardName boardName,
    @AuthenticationPrincipal UserDetailsImpl userDetails) throws IOException {

  postService.createPost(requestDto, gameType, gameName, boardName, file, userDetails);
  return ResponseEntity.ok(ApiResponse.ok("게시글 작성 성공", null));
}

 

MockMulitparFile을 이용하여 객체를 만들어준다.

@DisplayName("게시글 컨트롤러 테스트")
@WebMvcTest(PostController.class)
class PostControllerTest extends ControllerTest implements PostTest {

  @MockBean
  private PostService postService;

  @DisplayName("게시글 생성 - 성공")
  @Test
  @WithMockUser(authorities = {"USER"})
  void createPostSuccess() throws Exception {

    // given
    MockMultipartFile file = new MockMultipartFile(
        "file",
        "test-image.jpg",
        "image/jpeg",
        "uploadFile".getBytes(StandardCharsets.UTF_8));

    PostRequestDto requestDto = TEST_REQUEST_DTO;
    MockMultipartFile request = new MockMultipartFile(
        "requestDto", null, "application/json",
        objectMapper.writeValueAsString(requestDto).getBytes(StandardCharsets.UTF_8));

    // when
    var action = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/posts")
        .file(file)
        .file(request)
        .param("gameType", "PC_GAME")
        .param("gameName", "VALORANT")
        .param("boardName", "FREE_BOARD")
        .contentType(MediaType.MULTIPART_FORM_DATA)
        .accept(MediaType.APPLICATION_JSON));

    // then
    action.andExpect(MockMvcResultMatchers.status().isOk()).andDo(print());;
    verify(postService, times(1)).createPost(
        any(PostRequestDto.class), eq(GameType.PC_GAME),
        eq(GameName.VALORANT), eq(BoardName.FREE_BOARD),
        eq(file), any(UserDetailsImpl.class));
  }
public class ControllerTest implements UserTest {

  // 이 컨텍스트는 웹 애플리케이션의 빈들과 설정 정보 등을 관리하는데 사용
  @Autowired
  private WebApplicationContext context;

  // MockMvc는 웹 애플리케이션을 실제로 실행하지 않고도 컨트롤러를 테스트할 수 있는 도구
  @Autowired
  protected MockMvc mockMvc;

  // JSON 데이터를 Java 객체로 변환하거나 반대로 변환할 때 사용되는 Jackson 라이브러리의 ObjectMapper를 주입
  @Autowired
  protected ObjectMapper objectMapper;

  @BeforeEach
  void setUp() {
    mockMvc = MockMvcBuilders
        .webAppContextSetup(context)
        .build();

    // Mock 테스트 UserDetails 생성
    UserDetailsImpl testUserDetails = new UserDetailsImpl(TEST_USER);

    // SecurityContext 에 인증된 사용자 설정
    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
        testUserDetails, testUserDetails.getPassword(), testUserDetails.getAuthorities()));
  }

 

<참고>

https://velog.io/@songunnie/Spring-MockMvc-RequestPart-MultipartFile-%ED%85%8C%EC%8A%A4%ED%8A%B8-405-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0