[Test] Mockito.when() 사용 시 설정한 리턴 값이 나오지 않는 에러

이명범·2022년 8월 21일
0

트러블슈팅

목록 보기
4/8
post-thumbnail

문제

우선 코드를 보여드릴게요.

@Test
@WithAnonymousUser
@DisplayName("사용자는 회원 가입을 할 수 있어야 한다.")
public void joinTest() throws Exception {
    // given
    MemberJoinRequestDto dto = new MemberJoinRequestDto();

    dto.setId("mungmnb777");
    dto.setPassword("asd12345!");
    dto.setName("이명범");
    dto.setNickname("명범짱");
    dto.setGender("M");
    dto.setBirth("960513");
    dto.setTel("01045689094");
    dto.setSmoke("Y");
    dto.setAddress("우리집");

    Mockito.when(memberService.join(dto)).thenReturn(true);

    // when
    ResultActions actions = mockMvc.perform(MockMvcRequestBuilders.post("/member/join")
            .content(convertToJson(dto))
            .contentType(MediaType.APPLICATION_JSON)
            .with(SecurityMockMvcRequestPostProcessors.csrf()));

    // then
    actions.andExpect(MockMvcResultMatchers.status().isOk());
}

위의 코드는 MemberController의 회원가입 API를 테스트하는 코드입니다. 이 때 저는 memberService.join()을 실행할 때 Mock 객체가 해당 파라미터를 받는 경우 true를 리턴하도록 행동을 조작하였습니다.

코드를 작성한 후 테스트 코드를 돌려보니

상태 코드가 400으로 나왔어요😢

원인

원인은 알고보니 너무 간단했어요. Mock 객체 조작에 사용된 DTO와 컨트롤러에서 사용되는 DTO가 equals()로 동일 비교를 하는데, 해시 코드 값이 달라서 그런거였어요.

각각의 DTO의 해시 코드를 로그로 한번 찍어볼게요. 코드도 남겨 놓을게요!!

  • 테스트 코드
    @Test
    @WithAnonymousUser
    @DisplayName("사용자는 회원 가입을 할 수 있어야 한다.")
    public void joinTest() throws Exception {
        // given
        MemberJoinRequestDto dto = new MemberJoinRequestDto();
    
        dto.setId("mungmnb777");
        dto.setPassword("asd12345!");
        dto.setName("이명범");
        dto.setNickname("명범짱");
        dto.setGender("M");
        dto.setBirth("960513");
        dto.setTel("01045689094");
        dto.setSmoke("Y");
        dto.setAddress("우리집");
    
        Mockito.when(memberService.join(dto)).thenReturn(true);
    
        log.info("[테스트 코드 내부 DTO 해시코드] {}", dto);
    
        // when
        ResultActions actions = mockMvc.perform(MockMvcRequestBuilders.post("/member/join")
                .content(convertToJson(dto))
                .contentType(MediaType.APPLICATION_JSON)
                .with(SecurityMockMvcRequestPostProcessors.csrf()));
    
        // then
        actions.andExpect(MockMvcResultMatchers.status().isOk());
    }
  • 컨트롤러 코드
    @ApiOperation(value="회원 가입 API", notes="사용자가 회원 가입을 할 때 이용되는 API입니다.")
    @PostMapping("/join")
    public ResponseEntity<?> join(@Validated @RequestBody MemberJoinRequestDto dto) {
        log.info("[컨트롤러 내부 DTO 해시코드] {}", dto);
    
        if (memberService.join(dto)) {
            return new ResponseEntity<>(true, HttpStatus.OK);
        }
        else {
            return new ResponseEntity<>(false, HttpStatus.BAD_REQUEST);
        }
    }

이렇게 코드에 로그를 넣고 테스트를 돌려봤어요!

보시면 테스트 코드의 DTO 해시코드는 d164938이고 컨트롤러 내부 DTO 해시코드는 134ec0f3이네요

이 두 객체는 equals() 메서드를 사용했을 때 다른 객체이기 때문에 Mock 객체가 false를 리턴한거였어요.

해결

원인이 간단한 만큼 해결법도 간단했어요. MemberJoinRequestDtoequals()hashCode()를 재정의해주면 됩니다!!

저 같은 경우에는 롬복 @EqualsAndHashCode 애노테이션을 추가해주었습니다.

테스트도 잘 통과했네요!

profile
백엔드 개발자가 될거야

0개의 댓글