끄적끄적

[JUNIT] Mock Test 작성요령 본문

Back-end/Java

[JUNIT] Mock Test 작성요령

mashko 2021. 12. 7. 02:03
반응형

Junit을 이용해서 간단하게 몇가지 테스트코드 작성 예제를 기록해 두려한다.
일단 테스트코드의 필요성부터 알아보자

내가 무엇을 구현해야하는지 머리 속에 있는 또는 요구사항을 인/아웃풋에 대한 테스트코드로 미리 만들어둔다. 
테스트코드를 작성함으로써 테스트 시에 번거롭게 직접 API를 호출해보거나 결과를 일일히 확인 안해봐도 된다.
 - 개발 -> 실행 -> API 호출 -> 결과값에 대한 직접확인 -> 수정 -> 반복..
 - 위와같은 확인 방법을 개발 -> 테스트코드실행 -> 테스트코드 성공/실패 확인(간단해짐)
테스트코드를 잘 짜두면 아무래도 눈으로 직접확인하며 사람이 검증하는 것보다 확실하게 버그를 줄일 수 있다.
빌드 배포시에 테스트코드가 통과되야 배포가 되게 끔 설정해두면 서비스에 반영되기전 버그를 줄일 수 있다.
테스트코드에 아무래도 원하는 인/아웃에 대한 명확하게 의도가 들어가 있어 문서로서의 역활도 가능하다.
기타 등등... 굉장히 이점이 많다.
단점이라고 하면 테스트코드를 짜는 것에 대한 귀찮음(?)과 변경사항이 있을 때마다 테스트코드도 같이 관리를 해줘야 한다는 점?

그럼 Junit에서 테스트코드는 어떤식으로 작성하는지 간단한 테스트코드 예시를 보자.

    @Transactional(readOnly = true)
    public SignInResponse signIn(SignInRequestDto request) {
        UserDto user = userRepository.findByUserId(request.getUserId()).map(UserDto::new)
                .orElseThrow(() -> new ApiException("로그인 정보가 없습니다.", HttpStatus.BAD_REQUEST));

        if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            throw new ApiException("패스워드가 틀립니다.", HttpStatus.BAD_REQUEST);
        }

        String token = jwtTokenProvider.createToken(String.valueOf(user.getUserId()));

        SignInResponse result = new SignInResponse();

        result.setToken(token);

        return result;
    }

테스트케이스는 위의 코드를 위한 코드이다. 심심풀이로 만들고 있던 테스트코드 내용을 긁어왔다. 로그인 기능에 대한 코드이다.

그럼 위 코드의 실패 케이스에 대한 케이스 한개, 성공 케이스에 대한 케이스 한개로 나눠서보자

    @Test
    @DisplayName("로그인 서비스 성공 케이스")
    void signIn() {
        // given
        SignInRequestDto request = new SignInRequestDto();

        request.setUserId("test1");
        request.setPassword("1234");

        // when
        UserOrm userOrm = new UserOrm();

        userOrm.setUserId(request.getUserId());
        userOrm.setPassword("$2y$10$lvrwYg8h7LSMSDo/i8HrwOuR3gD/lC4oYYF7YevobQ2xw7xJ8WHsm");

        when(userRepository.findByUserId(request.getUserId())).thenReturn(Optional.of(userOrm));
        when(jwtTokenProvider.createToken(String.valueOf(user.getUserId()))).thenReturn(this.testToken);

        SignInResponse result = userService.signIn(request);

        // then
        assertThat(result).isNotNull();
        assertThat(result.getToken()).isEqualTo(this.testToken);
    }

given에 해당되는 부분이 인풋에 대한 정의이고, when에 해당되는 부분이 실행 구절에 대한 정의이고, then 부분이 결과에 대한 검증 처리를 정의한 구간이다.
해당 request(요청)일 경우 실행은 userOrm과 토큰에 대한 값이 나와야 되게 정의해두고
실제로 userService.signIn(request);이 실행되었을 경우 최종 결과값이 내가 예상한 결과대로 나왓는지 체크하는 로직이다.

예상대로 성공했다. 실패할때에는 어떻게 나오는지 확인해보자

일부로 패스워드를 틀리게 하고 넣어봤다.
정확히 패스워드 때문에 틀린 부분에 대한 지적을 해준다.
이번엔 패스워드에 대한 실패일 경우에 대해 실패 케이스를 만들어보자

    @Test
    @DisplayName("로그인 서비스 실패 테스트")
    void signInFailed() {
        try {
            SignInRequestDto request = new SignInRequestDto();

            request.setUserId("test1");
            request.setPassword("1235");

            UserOrm userOrm = new UserOrm();

            userOrm.setUserId(request.getUserId());
            userOrm.setPassword("$2y$10$lvrwYg8h7LSMSDo/i8HrwOuR3gD/lC4oYYF7YevobQ2xw7xJ8WHsm");

            when(userRepository.findByUserId(request.getUserId())).thenReturn(Optional.of(userOrm));

            SignInResponse result = userService.signIn(request);
        } catch (ApiException e) {
            assertThat(e.getHttpStatus()).isEqualTo(HttpStatus.BAD_REQUEST);
            assertThat(e.getMessage()).isEqualTo("패스워드가 틀립니다.");
        }
    }

try-catch를 통해 일부로 비밀번호를 다르게 만들어두고 catch에서 정의해둔 404와 메세지가 일치하는지 확인하는 케이스를 정의해 두었다.

제대로 돌아가는지 성공했다. 이번엔 그럼 정말로 제대로 돌아가는지 확인해보자

메세지 부분에서 문자 일부를 지워서 정합성이 맞지 않게 했더니 틀리게 나오는 부분에 대해 잡아준다.

이렇게 간단하게만 테스트코드를 작성해도 실수로 변경하지 않은 부분이 있거나, 사람의 실수로 인한 버그들은 왠만하면 잡힌다.
로그인 부분말고도 이곳 저곳 단위테스트를 작성해두면 더 세세하게 잡힐 것이고 에러포인트에 대해 디버깅을 하지 않아도 딱 잡아준다.

https://github.com/joys1006/springboot-sample-project/blob/master/java-server/src/test/java/com/toy/javaserver/api/domain/user/service/UserServiceTest.java

 

GitHub - joys1006/springboot-sample-project

Contribute to joys1006/springboot-sample-project development by creating an account on GitHub.

github.com

 

반응형
Comments