HTTP DELETE 요청에는 @WithCustomMockUser이 없어도 테스타가 성공되는 이유

박준수·2023년 9월 30일
0

이것저것

목록 보기
7/9

DiaryController

 	@Operation(summary = "일기 삭제")
  @DeleteMapping("/{diaryId}")
  public ResponseEntity<ResultResponse> deleteDiary(@AuthenticationPrincipal UserDetail user,
                                                    @PathVariable Long diaryId){
      diaryService.deleteDiary(user, diaryId);
      return ResponseEntity.ok(ResultResponse.of(ResultCode.DIARY_DELETE_SUCCESS));
  }
  • 다음은 DiaryController에서 사용자가 작성한 일기를 삭제하는 메서드이다.
  • 일기를 삭제할 때도 인증된 사용자인지 확인하기 위해 @AuthenticationPrincipal UserDetail user 이 부분이 들어가 있다.

DeleteDiary TestCode

  @Test
  @WithCustomMockUser
  @DisplayName("사용자가 작성한 일기가 PK로 삭제될 수 있다.")
  void deleteDiary() throws Exception {
      //given
      doNothing().when(diaryService).deleteDiary(any(), any());

      //when
      ResultActions perform =
              mockMvc.perform(
                      delete("/diaries/{diaryId}", 1L));
      //then
      perform.andExpect(status().isOk());

      //docs
      perform.andDo(print())
              .andDo(document("delete diary",
                      getDocumentRequest(),
                      getDocumentResponse()));
  }
  • @WithCustomMockUser은 @AuthenticationPrincipal UserDetail 을 테스트하기 위한 인증된 사용자를 미리 만든 커스텀어노테이션이다.
  • 따라서 당연히 다음 테스트 코드에서 @WithCustomMockUser을 사용했다.

문제 상황

@WithCustomMockUser을 빼도 성공이 된다.

  • 아니 Controller에서 @AuthenticationPrincipal UserDetail이 들어가 있는데 왜 빼도 성공이 되는걸까??

문제 해결 과정

그러나 @DeleteMapping 요청의 경우, 일반적으로 HTTP DELETE 요청은 본문(body) 데이터를 전송하지 않습니다. 따라서 @AuthenticationPrincipal을 사용하여 UserDetail 객체를 직접 매개변수로 받는 것은 일반적으로 사용되지 않습니다. 대신에 @AuthenticationPrincipal은 주로 HTTP POST 또는 PUT 요청과 같이 본문 데이터가 있는 요청에서 사용됩니다.

CreateDiary

  @Operation(summary = "일기 등록")
  @PostMapping
  public ResponseEntity<ResultResponse> createDiary(@AuthenticationPrincipal UserDetail user,
                                                    @RequestPart("file") MultipartFile multipartFile,
                                                    @Valid @RequestPart(value="createRequest") DiaryCreateReq createRequest) throws IOException {
      String drawingUrl = s3UploadService.saveFile(multipartFile, user.getUsername());
      diaryService.createDiary(user, createRequest, drawingUrl);
      return ResponseEntity.ok(ResultResponse.of(ResultCode.DIARY_CREATE_SUCCESS));
  }
  • 다음과 같이 일기를 등록하는 Controller 메서드는 POST 요청을 보넨다.

CreateDiary TestCode

  @Test
  @DisplayName("일기가 등록될 수 있다.")
  void createDiary() throws Exception {
      //given
      MockMultipartFile file = new MockMultipartFile(
              "file",      // 파라미터 이름
              "file_name", // 파일 이름
              "image/jpeg",// 파일 타입
              "test file".getBytes(StandardCharsets.UTF_8) // 파일 내용
      );
      given(s3UploadService.saveFile(any(), any())).willReturn(String.valueOf(file));

      DiaryCreateReq createReq = DiaryControllerFixture.CREATE_REQ;
      String jsonByCreateReq = objectMapper.writeValueAsString(createReq);
      MockMultipartFile request = new MockMultipartFile(
              "createRequest",
              "createRequest",
              "application/json",
              jsonByCreateReq.getBytes(StandardCharsets.UTF_8)
      );
      String token = "accessToken";
      diaryService.createDiary(any(), any(), any());

      //when
      ResultActions perform =
              mockMvc.perform(
                      multipart("/diaries")
                              .file(file)
                              .file(request)
                              .header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
              );

      // then
      perform.andExpect(status().isOk());

      // docs
      perform.andDo(print())
              .andDo(document("register diary",
                      getDocumentRequest(),
                      getDocumentResponse()));

  }

  • 다음과 같이 POST 요청에서는 @WithCustomMockUser 이 없으면 null이 들어가 에러가 발생하게 된다.

결론

    @Test
    @DisplayName("사용자가 작성한 일기가 PK로 삭제될 수 있다.")
    void deleteDiary() throws Exception {
        //given
        doNothing().when(diaryService).deleteDiary(any(), any());

        //when
        ResultActions perform =
                mockMvc.perform(
                        delete("/diaries/{diaryId}", 1L));
        //then
        perform.andExpect(status().isOk());

        //docs
        perform.andDo(print())
                .andDo(document("delete diary",
                        getDocumentRequest(),
                        getDocumentResponse()));
    }
  • 따라서 다음과 같이 DeleteMapping Controller 메서드를 작성할수 있었다~
profile
방구석개발자

0개의 댓글