[TIL] 23. 03.09 mockito 이용한 테스트 JwtUtil 주입 때 발생한 에러 및 해결

hyewon jeong·2023년 3월 9일
0

TIL

목록 보기
104/140

1 발생

userService를 모키토를 이용한 단위 테스트 중
jwtUtil 을 @Spy로 선언 하니 아래와 같은 에러 발생

Please ensure that the type 'JwtUtil' has a no-arg constructor.

JwtUtil에 빈생성자가 있는지 확인 해라.~


2 코드

jwtUtil

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtUtil {

  public static final String AUTHORIZATION_HEADER = "Authorization";
  public static final String REFRESH_TOKEN_HEADER = "RefreshToken";
  public static final String AUTHORIZATION_KEY = "auth";
  private static final String BEARER_PREFIX = "Bearer ";
  private static final long TOKEN_TIME = 30 * 60 * 1000L; //30 min

  private static final long REFRESH_TOKEN_TIME = 60 * 60 * 1000L * 24 * 14; //2week

  private final UserDetailsServiceImpl userDetailService;
  @Value("${jwt.secret.key}")
  private String secretKey;
  private Key key;
  private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

Test

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

  @Mock
  private UserRepository userRepository;
  @InjectMocks
  private UserService userService;

  @Spy
  private JwtUtil jwtUtil;

  @BeforeEach
  void prepare() {
    ReflectionTestUtils.setField(jwtUtil,
        "secretKey", // jwtUtil의 secretKey값이 저장될 변수
        "7ZWt7ZW0OTntmZTsnbTtjIXtlZzqta3snYTrhIjrqLjshLjqs4TroZzrgpjslYTqsIDsnpDtm4zrpa3tlZzqsJzrsJzsnpDrpbzrp4zrk6TslrTqsIDsnpA="); // secretKey의 값
    jwtUtil.init(); // jwtUtil에서 @PostConstructor가 동작하지 않기 때문에, 임의로 실행시켜야 함
  }

  @Spy
  private BCryptPasswordEncoder passwordEncoder;


  @Test
  @DisplayName("회원가입")
  void signup() {
    //given 입력값 리턴값
    SignupRequest request = SignupRequest.builder()
        .username("pororo")
        .password("pororo1234")
        .email("pororo@naver.com")
        .admin(false)
        .adminToken(null)
        .build();

    when(userRepository.findByUsername(any(String.class)))
        .thenReturn(Optional.empty());
    //when
    ResponseStatusDto response = userService.signup(request);

    //then
    assertThat(response.getStatusCode()).isEqualTo(StatusEnum.SIGNUP_SUCCESS.getStatusCode());
    assertThat(response.getMsg()).isEqualTo(StatusEnum.SIGNUP_SUCCESS.getMsg());

    verify(userRepository, times(1)).save(any(User.class));
  }

3 원인

그래서 위의 기존 코드에 @NoArgsConstructor를 입력하면 위에 private final 로 선언된UserDetailsServiceImpl userDetailService에 빨간줄로 에러가 발생한다. 빨간줄의이유는 @NoArgsConstructor로 빈생성자를 만들지만 final로 선언했지않는가? 그래서 매게변수를 꼭! 가져야하기 때문에 오류가 발생한다.
그럼 현재 코드에서 빈생성자를 사용하지 않고 , 테스트 코드에서 jwtUtil을 빈으로 주입하는 방법은??


4 해결

@InjectMocks으로 jwtUtil을 주입하면 된다.

  @InjectMocks
  private JwtUtil jwtUtil;

테스트 코드

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

  @Mock
  private UserRepository userRepository;
  @InjectMocks
  private UserService userService;

  @InjectMocks
  private JwtUtil jwtUtil;

  @BeforeEach
  void prepare() {
    ReflectionTestUtils.setField(jwtUtil,
        "secretKey", // jwtUtil의 secretKey값이 저장될 변수
        "7ZWt7ZW0OTntmZTsnbTtjIXtlZzqta3snYTrhIjrqLjshLjqs4TroZzrgpjslYTqsIDsnpDtm4zrpa3tlZzqsJzrsJzsnpDrpbzrp4zrk6TslrTqsIDsnpA="); // secretKey의 값
    jwtUtil.init(); // jwtUtil에서 @PostConstructor가 동작하지 않기 때문에, 임의로 실행시켜야 함
  }

  @Spy
  private BCryptPasswordEncoder passwordEncoder;


  @Test
  @DisplayName("회원가입")
  void signup() {
    //given 입력값 리턴값
    SignupRequest request = SignupRequest.builder()
        .username("pororo")
        .password("pororo1234")
        .email("pororo@naver.com")
        .admin(false)
        .adminToken(null)
        .build();

    when(userRepository.findByUsername(any(String.class)))
        .thenReturn(Optional.empty());
    //when
    ResponseStatusDto response = userService.signup(request);

    //then
    assertThat(response.getStatusCode()).isEqualTo(StatusEnum.SIGNUP_SUCCESS.getStatusCode());
    assertThat(response.getMsg()).isEqualTo(StatusEnum.SIGNUP_SUCCESS.getMsg());

    verify(userRepository, times(1)).save(any(User.class));
  }

profile
개발자꿈나무

0개의 댓글