T_era

테스트 코드 mock()과 ReflectionTestUtils 본문

Programing/Spring

테스트 코드 mock()과 ReflectionTestUtils

블스뜸 2025. 6. 9. 16:26

Mockito의 mock()과 ReflectionTestUtils 정리

1. mock() 메서드

기본 개념

  • Mockito의 정적 메서드로, Mock 객체를 생성
  • @Mock 어노테이션과 동일한 기능을 수행하지만, 코드에서 직접 호출
  • 테스트 메서드 내에서 일시적으로 Mock 객체가 필요할 때 유용

사용 예

@Test
void test_with_mock() {
    // Mock 객체 생성
    UserRepository userRepository = mock(UserRepository.class);
    PasswordEncoder passwordEncoder = mock(PasswordEncoder.class);
    
    // Mock 객체 동작 정의
    when(userRepository.findById(1L)).thenReturn(Optional.of(new User()));
    when(passwordEncoder.encode("password")).thenReturn("encodedPassword");
    
    // 테스트 대상 객체에 Mock 주입
    UserService userService = new UserService(userRepository, passwordEncoder);
    
    // 테스트 실행
    userService.changePassword(1L, new UserChangePasswordRequest("old", "new"));
    
    // 검증
    verify(userRepository).findById(1L);
}

 

@Mock vs mock()

@Mock
UserRepository userRepository;

// mock() 사용
UserRepository userRepository = mock(UserRepository.class);

2. ReflectionTestUtils

 
 

기본 개념

  • Spring Framework의 테스트 유틸리티
  • private 필드에 접근하거나 값을 설정할 때 사용
  • 리플렉션을 사용하여 객체의 private 멤버에 접근

주요 메서드

  1. setField(): private 필드에 값 설정
  2. getField(): private 필드의 값 조회
  3. invokeMethod(): private 메서드 호출

사용 예시

@Test
void test_private_field() {
    // given
    UserService userService = new UserService();
    UserRepository userRepository = mock(UserRepository.class);
    
    // private 필드에 Mock 객체 주입
    ReflectionTestUtils.setField(userService, "userRepository", userRepository);
    
    // when
    when(userRepository.findById(1L)).thenReturn(Optional.of(new User()));
    
    // then
    User user = userService.findUser(1L);
    assertThat(user).isNotNull();
}

2. private 필드 값 조회

@Test
void test_get_private_field() {
    // given
    UserService userService = new UserService();
    UserRepository userRepository = mock(UserRepository.class);
    ReflectionTestUtils.setField(userService, "userRepository", userRepository);
    
    // when
    Object fieldValue = ReflectionTestUtils.getField(userService, "userRepository");
    
    // then
    assertThat(fieldValue).isEqualTo(userRepository);
}
 

3. private 메서드 호출

@Test
void test_private_method() {
    // given
    UserService userService = new UserService();
    
    // when
    String result = (String) ReflectionTestUtils.invokeMethod(
        userService,
        "validatePassword",
        "password123"
    );
    
    // then
    assertThat(result).isNotNull();
}
 

실제 사용 예시

1. 의존성 주입 테스트

 
java
 
Apply to build.gradle

2. private 메서드 테스트

@Test
void test_private_validation() {
    // given
    UserService userService = new UserService();
    
    // when
    boolean result = (boolean) ReflectionTestUtils.invokeMethod(
        userService,
        "isValidPassword",
        "password123"
    );
    
    // then
    assertThat(result).isTrue();
}
 

주의사항

  1. ReflectionTestUtils는 테스트 코드에서만 사용
  2. private 멤버에 접근하는 것은 캡슐화를 깨뜨릴 수 있음
  3. 가능하면 public 메서드를 통해 테스트하는 것이 좋음
  4. 꼭 필요한 경우에만 사용

사용이 필요한 경우

  1. private 필드에 의존성 주입이 필요한 경우
  2. private 메서드의 로직을 직접 테스트해야 하는 경우
  3. 테스트를 위해 private 필드의 값을 확인해야 하는 경우
  4. Spring의 자동 주입이 어려운 테스트 환경에서 사용