💡 .java를 클릭시 관련 커밋으로 이동💡
회고
Entitiy 조회보단 -> Dto 조회가 성능상 유리
QueryDsl에서 exist 메서드 쓰는것보다 JPA의 exists() 메서드를 사용했다. 그이유가 JPA exists()메서드는 선택된 항이 하나라도 존재하면 즉시 처리를 멈추고 결과를 반환하는데 QueryDsl exist 메서드는 실제로 count() > 0 으로 실행한다.
// 참고한 자료
https://www.youtube.com/watch?v=zMAX7g6rO_Y
@Test
void 닉네임_중복체크_테스트_중복인경우() {
// given
userRepository.save(generateAuthUser());
UserNameRequest request = UserFixture.generateUserNameRequest("이름");
// then
assertThrows(UserException.class, () -> {
authService.nickNameDuplicationCheck(request);
}, ExceptionMessage.USER_NAME_DUPLICATION.getText());
}
테스트를 작성하면서 신기한 점을 발견했다. // then 부분에서 ExceptionMessage.USER_NAME_DUPLICATION.getText() 이부분을 다른 예외 메시지로 바꿔도 통과가 되버리는 상황이 발생했는데..
찾아보니 JUnit에서 assertThrows() 메서드를 사용할때는 두가지 방법으로 예외를 검증한다.
- 예외 타입만 검증하는 경우 위의 코드처럼 예외가 발생하는 지만 검증한다. 즉, 예외 메시지는 따로 검증하지 않는다.
- 예외 타입과 메시지를 검증하는 경우는 아래와 같다.
UserException em = assertThrows(UserException.class, () -> {
authService.nickNameDuplicationCheck(request);
});
assertEquals(ExceptionMessage.USER_NAME_DUPLICATION.getText(), em.getMessage());
이코드로 두단계를 걸쳐 예외가 발생하는지 검증하고 그다음 예외 메시지를 따로 검증해야 한다!!!
@ApiResponse(responseCode = "200", description = "닉네임 중복 검사 성공")
@PostMapping("/check-nickname")
public JsonResult<?> nickNameDuplicationCheck(@Valid @RequestBody UserNameRequest request) {
authService.nickNameDuplicationCheck(request);
return JsonResult.successOf("Nickname Duplication Check Success.");
}
닉네임 중복검사를 위한 컨트롤러 구현이다.
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserNameRequest {
@NotBlank(message = "이름은 공백일 수 없습니다.")
@Size(max = 6, message = "이름 6자 이내")
private String name; // 이름
}
User가 작성하는 이름 DTO 이다.
// 닉네임 중복체크 메서드
public void nickNameDuplicationCheck(UserNameRequest request) {
boolean exists = userRepository.existsByName(request.getName());
if (exists) {
log.warn(">>>> {} : {} <<<<", request.getName(), ExceptionMessage.USER_NAME_DUPLICATION);
throw new UserException(ExceptionMessage.USER_NAME_DUPLICATION);
}
}
existsByName() 메서드를 통해 데이터베이스에 같은 이름이 있는지 검사를 한다. 만약 있을 경우 true로 반환되어 예외가 터진다.
// 같은 Name(닉네임)이 있는지 판별한다.
boolean existsByName(String name);
테스트
@Test
void 닉네임_중복체크_테스트() throws Exception {
// given
UserNameRequest request = UserFixture.generateUserNameRequest("이정우");
doNothing().when(authService).nickNameDuplicationCheck(any(UserNameRequest.class));
// when & then
mockMvc.perform(post("/auth/check-nickname")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
// then
.andExpect(status().isOk())
.andExpect(jsonPath("$.res_code").value(200))
.andExpect(jsonPath("$.res_msg").value("OK"))
.andExpect(jsonPath("$.res_obj").value("Nickname Duplication Check Success."))
.andDo(print());
}
@Test
void 닉네임_중복체크_유효성_검증_실패_테스트1() throws Exception {
// given
String inValidName = " ";
String expectedError = "name: 이름은 공백일 수 없습니다.";
UserNameRequest request = UserFixture.generateUserNameRequest(inValidName);
doNothing().when(authService).nickNameDuplicationCheck(any(UserNameRequest.class));
// when
mockMvc.perform(post("/auth/check-nickname")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
// then
.andExpect(status().isOk())
.andExpect(jsonPath("$.res_code").value(400))
.andExpect(jsonPath("$.res_msg").value(expectedError))
.andDo(print());
}
@Test
void 닉네임_중복체크_유효성_검증_실패_테스트2() throws Exception {
// given
String inValidName = "이름은6자이내";
String expectedError = "name: 이름 6자 이내";
UserNameRequest request = UserFixture.generateUserNameRequest(inValidName);
doNothing().when(authService).nickNameDuplicationCheck(any(UserNameRequest.class));
// when
mockMvc.perform(post("/auth/check-nickname")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
// then
.andExpect(status().isOk())
.andExpect(jsonPath("$.res_code").value(400))
.andExpect(jsonPath("$.res_msg").value(expectedError))
.andDo(print());
}
동작이 잘 되는지 컨트롤러 테스트인데 추가적으로 이름을 보내는 DTO에서 유효성 검증에 실패하는 경우를 나누어서 테스트했다.
@Test
void 닉네임_중복체크_테스트_중복인경우() {
// given
userRepository.save(generateAuthUser());
UserNameRequest request = UserFixture.generateUserNameRequest("이름");
// then
UserException em = assertThrows(UserException.class, () -> {
authService.nickNameDuplicationCheck(request);
});
assertEquals(ExceptionMessage.USER_NAME_DUPLICATION.getText(), em.getMessage());
}
@Test
void 닉네임_중복체크_테스트_중복이아닌경우() {
// given
userRepository.save(generateAuthUser());
UserNameRequest request = UserFixture.generateUserNameRequest("이정우");
// when
authService.nickNameDuplicationCheck(request);
// then
assertDoesNotThrow(() -> authService.nickNameDuplicationCheck(request));
}
중복인 경우와 중복이 아닌 경우를 확인하는 Service 테스트이다.
public static UserNameRequest generateUserNameRequest(String name) {
return UserNameRequest.builder()
.name(name)
.build();
}
DTO를 전달하기 위한 테스트용 Fixture 작성
'Project > 깃터디 (gitudy)' 카테고리의 다른 글
[깃터디/Todo] Todo 조회 api 구현 (0) | 2024.05.11 |
---|---|
[깃터디/Todo] Todo 등록 api 구현 (0) | 2024.05.11 |
[깃터디/Auth] 회원 정보 조회 구현 (0) | 2024.05.10 |
[깃터디/Auth] 로그아웃 요청 구현 (0) | 2024.05.10 |
[깃터디/Auth] 로그인 페이지 요청 구현 (0) | 2024.05.10 |
댓글