-
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()); }