우선 코드를 보여드릴게요.
@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
를 리턴한거였어요.
원인이 간단한 만큼 해결법도 간단했어요. MemberJoinRequestDto
에 equals()
와 hashCode()
를 재정의해주면 됩니다!!
저 같은 경우에는 롬복 @EqualsAndHashCode
애노테이션을 추가해주었습니다.
테스트도 잘 통과했네요!