ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Test code 중복 코드에 대한 고민
    카테고리 없음 2023. 5. 16. 16:59

     

    아래는 개인 프로잭트 Lotto 로그인 Service 코드이다

    public String signIn(SigninRequest request) {
       User user = findByUser(request.getEmail());
    
       if (redisTemplate.opsForValue().get(RTK + user.getId()) != null) {
          redisTemplate.delete(RTK + user.getId());
          throw new IllegalArgumentException("중복 로그인입니다");
       }
    
       if (!user.getStatus().equals(Status.ACTIVE)) {
          switch (user.getStatus()) {
             case SUSPENDED -> throw new IllegalArgumentException("정지된 계정입니다");
             case DORMANT -> throw new IllegalArgumentException("탈퇴한 계정입니다");
             default -> throw new IllegalArgumentException("잘못된 상태정보입니다");
          }
       }
    
       if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
          throw new IllegalArgumentException("아이디 또는 비밀번호를 잘못 입력하셨습니다");
       }
    
       String refreshToken = jwtProvider.refreshToken(user.getEmail(), user.getId());
       redisTemplate.opsForValue().set(RTK + user.getId(), refreshToken);
    
       return jwtProvider.accessToken(user.getEmail(), user.getId());
    }

     

    실패 사례(?) Exception test 하는 도중 Status 의 개수 많큼 중복 코드가 생성되는데 일단 모두 작성했다

    UserServiceTest 가 구현, 구동 되고 리팩토링 하는 과정에서 중복 코드들을 걷어내는 과정에서 드라마틱하게 중복 코드 처리를 도와준 코드들을 소개하고 정리해보겠다.

     

    @ParameterizedTest : 하나의 테스트 메소드로 여러 개의 파라미터에 대해서 테스트할 수 있다

    @MethodSource : 참조할 사용자 지정 메서드 위치를 지정함 예 : "page#method"

    @ValueSource : 리터럴 값의 단일 배열을 지정, 매개 변수화 된 테스트 호출마다 단일 인수를 제공하는 데 사용

     

    필자는 정적으로 만들어진 saveUser 가 있고 setStatus(); 매개변수로 특정 String 값을 넣으면 되기에 처음엔 ValueSource 를 사용해 strings = { "TEST", "SUSPENDED", "DORMANT" } 해당 값을 넣어주려 했지만 다른 class 에서도 사용하며, TEST 를 switch 에 추가 해야하기에 @MethodSource 사용하여 Arguments 를 이용

     

    public static Stream<Arguments> statusTestData() {
       return Stream.of(
          Arguments.of(Status.SUSPENDED),
          Arguments.of(Status.DORMANT),
          Arguments.of(Status.TEST)
       );
    }

    Arguments.of() 단일 테스트 인수들이며 캡슐화하여 반환

     

    @ParameterizedTest
    @MethodSource("com.example.sixnumber.fixture.TestDataFactory#statusTestData")
    void signin_fail_Status(Status status) {
       User user = mock(User.class);
       when(user.getStatus()).thenReturn(status);
    
       when(userRepository.findByEmail(anyString())).thenReturn(Optional.of(user));
    
       when(redisTemplate.opsForValue()).thenReturn(valueOperations);
       when(valueOperations.get(anyString())).thenReturn(null);
    
       Assertions.assertThrows(IllegalArgumentException.class,
          () -> userService.signIn(signinRequest));
    
       verify(userRepository).findByEmail(anyString());
       verify(valueOperations).get(anyString());
    }

     

Designed by Tistory.