회원가입 유효성 검사와 단위 테스트 작성

최준호·2022년 1월 10일
0

eats

목록 보기
9/13
post-thumbnail

🔨 유효성 검사 추가

지난 포스트에서 @Valid를 사용하여 유효성 검사를 진행했는데 값이 빈 값인지 체크하는 것 이외에도 다른 유효성 검사를 추가로 해야해서 유효성 검사를 추가하려고 한다.

@Transactional
@Override
public MemberVo join(MemberDto md){
    //join에 대한 유효성 검사 method
    joinValidation(md);

    String id = md.getId();
    String pw = md.getPw();
    String email = md.getEmail();

    Set<String> roles = new HashSet<>();
    roles.add(MemberRoles.MEMBER.getRole());

    MemberEntity me = MemberEntity.builder()
            .id(id)
            .pw(passwordEncoder.encode(pw)) //비밀번호 암호화
            .email(email)
            .auth(roles)
            .build();

    MemberEntity save = loginRepository.save(me);

    return MemberVo.builder().id(save.getId()).build();
}
//그 외 유효성 검사
private void joinValidation(MemberDto md){
    //pw와 rePw이 같은 값인지 체크
    if(!md.getPw().equals(md.getRePw())) throw new JoinValidException(JoinValidExceptionMsg.RE_PW_FAIL.getMsg(), HttpStatus.BAD_REQUEST);
    //email 형식 체크
    if(!md.getEmail().contains("@")) throw new JoinValidException(JoinValidExceptionMsg.EMAIL_FAIL.getMsg(), HttpStatus.BAD_REQUEST);
}

그 후에 joinValidation() 메서드를 추가로 작성하여 내가 하려는 유효성 검사를 진행했다.

@AllArgsConstructor
@Getter
public enum JoinValidExceptionMsg {
    RE_PW_FAIL("두 비밀번호가 일치하지 않습니다."),
    EMAIL_FAIL("이메일 형식을 확인해주세요.")
    ;
    private String msg;
}

테스트 코드를 작성하기 전 유효성 검사 에러 메세지와 테스트 코드 기대 에러 메세지의 내용을 좀 더 코드로 보여주기 쉽게 만들기 위해 enum 클래스를 작성했다.

유효성 검사의 Exception을 진행하기 위해 Exception의 생성자와 advice의 코드를 수정했다.

@NoArgsConstructor
@AllArgsConstructor
@Getter
public class JoinValidException extends RuntimeException {
    private String msg;
    private HttpStatus status;
    private List<ObjectError> allErrors = new LinkedList<>();

    public JoinValidException(String msg, HttpStatus status) {
        this.msg = msg;
        this.status = status;
    }
}

오류 list가 없을 경우를 위해 컬렉션 객체를 받지 않는 생성자를 추가로 만들었다.

@ExceptionHandler(JoinValidException.class)
public ResponseEntity joinValidException(JoinValidException jve){
    List<ObjectError> allErrors = jve.getAllErrors();

    List<CommonError> errorList = new ArrayList<>();
    if(allErrors.isEmpty()){
        CommonError commonError = new CommonError(jve.getMsg());
        errorList.add(commonError);
    }else{
        for(ObjectError oe : allErrors){
            String detail = ((FieldError)oe).getField() + " " + oe.getDefaultMessage();
            CommonError commonError = new CommonError(jve.getMsg(), detail);
            errorList.add(commonError);
        }
    }

    CommonErrorV1<List<CommonError>> result = new CommonErrorV1<>(errorList);
    return new ResponseEntity<CommonErrorV1>(result, jve.getStatus());
}

advice 또한 컬렉션 객체가 들어왔을 때와 들어오지 않았을 때를 분기처리하여 작성하였다.

테스트 코드 작성

@SpringBootTest
@Transactional(readOnly = true)
class LoginServiceImplTest {

    @Autowired
    LoginService loginService;

    @Test
    @DisplayName("rePw 불일치")
    void joinRePwFail(){
        //given
        MemberDto md = new MemberDto();
        md.setId("testId");
        md.setPw("password1");
        md.setRePw("password2");    //불일치
        md.setEmail("mail@mail.com");

        //when
        JoinValidException joinValidException = assertThrows(JoinValidException.class, () -> loginService.join(md));
        //then
        assertEquals(JoinValidExceptionMsg.RE_PW_FAIL.getMsg(),joinValidException.getMsg());
    }

    @Test
    @DisplayName("잘못된 email 형식")
    void joinEmailFail(){
        //given
        MemberDto md = new MemberDto();
        md.setId("testId");
        md.setPw("password1");
        md.setRePw("password1");
        md.setEmail("mail.com");    //형식 오류

        //when
        JoinValidException joinValidException = assertThrows(JoinValidException.class, () -> loginService.join(md));
        //then
        assertEquals(JoinValidExceptionMsg.EMAIL_FAIL.getMsg(),joinValidException.getMsg());
    }
}

지난 포스트에서는 통합 테스트를 진행했다면 이번 포스트에서는 단위 테스트를 진행한다. 통합 테스트도 중요하지만 단위 테스트는 class나 method 단위로 테스트를 진행하기 때문에 매우 중요하다.

👍 이번 포스트를 통해 느낀점

  1. 유효성 검사를 method화 시켜서 코드를 좀 더 보기 좋게 만들었다.
  2. exception 처리를 위해 exception 코드의 생성자를 더 추가하고 advice를 수정하여 진행하였는데. 여기서 생성자의 개념을 명확하게 사용할 수 있는 학습 기회였다.
  3. 유효성 검사에서의 에러 메세지와 테스트 코드의 에러 메세지의 통일을 위해서 enum 클래스를 작성하여 적용하였는데 코드의 통일성을 줄수 있게 되었다.
profile
해당 주소로 이전하였습니다. 감사합니다. https://ililil9482.tistory.com

0개의 댓글