T_era
테스트 코드 어노테이션 및 메서드 정리 본문
Mockito 어노테이션과 메서드 검증에 대한 정리
1. Mockito 어노테이션
@Mock
- 가짜 객체를 생성하는 어노테이션
- 실제 객체의 동작을 시뮬레이션할 수 있음
- 모든 메서드가 기본값을 반환 (null, 0, false 등)
- 주로 외부 의존성을 가진 객체를 테스트할 때 사용
@Mock
UserRepository userRepository; // 가짜 객체 생성
// 사용 예시
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
@InjectMocks
- 생성된 가짜 객체를 주입받는 클래스에 사용
- @Mock으로 생성된 객체들을 자동으로 주입
- 주로 테스트 대상 클래스에 사용
@Mock
UserRepository userRepository;
@InjectMocks
UserService userService; // userRepository가 자동으로 주입됨
@Spy
- 실제 객체와 메서드 모킹을 모두 사용해야 할 때 사용
- 실제 객체의 메서드를 호출하되, 필요한 경우에만 특정 메서드를 오버라이드
- 선언과 동시에 초기화해야 함
- 실제 객체의 대부분의 동작을 유지하면서 특정 메서드만 모킹할 때 유용
@Spy
JwtUtil jwtUtil = new JwtUtil(); // 선언과 동시에 초기화
// 사용 예시
doReturn("mocked_token").when(jwtUtil).createToken(anyLong(), anyString(), any());
2. 메서드 사용 검증
verify()
- Mock 객체의 메서드 호출을 검증
- 호출 횟수, 호출 순서, 호출 인자 등을 검증 가능
verify(userRepository).findById(1L);
// 호출 횟수 검증
verify(userRepository, times(2)).findById(1L);
verify(userRepository, never()).delete(any());
verify(userRepository, atLeastOnce()).save(any());
// 호출 순서 검증
InOrder inOrder = inOrder(userRepository);
inOrder.verify(userRepository).findById(1L);
inOrder.verify(userRepository).save(any());
verifyNoMoreInteractions()
- Mock 객체의 추가적인 메서드 호출이 없는지 검증
- 예상치 못한 메서드 호출을 방지
verify(userRepository).findById(1L);
verifyNoMoreInteractions(userRepository); // 다른 메서드 호출이 없어야 함
3. given()과 when()의 차이
when()
- Mockito의 기본 메서드
- 전통적인 테스트 스타일에서 사용
- 문법: when(mock.method()).thenReturn(value)
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
given()
- BDD(Behavior Driven Development) 스타일의 테스트를 위한 메서드
- 더 자연스러운 문장처럼 읽힘
- 문법: given(mock.method()).willReturn(value)
given(userRepository.findById(1L)).willReturn(Optional.of(user));
4. 실제 사용 예시
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private PasswordEncoder passwordEncoder;
@InjectMocks
private UserService userService;
@Test
void signup_success() {
// given
SignupRequest request = new SignupRequest("test@test.com", "password", "USER");
User user = new User("test@test.com", "encodedPassword", UserRole.USER);
// given
given(userRepository.existsByEmail(anyString())).willReturn(false);
given(passwordEncoder.encode(anyString())).willReturn("encodedPassword");
given(userRepository.save(any(User.class))).willReturn(user);
// when
SignupResponse response = userService.signup(request);
// then
assertThat(response.getBearerToken()).isNotNull();
// verify
verify(userRepository).existsByEmail(request.getEmail());
verify(passwordEncoder).encode(request.getPassword());
verify(userRepository).save(any(User.class));
verifyNoMoreInteractions(userRepository, passwordEncoder);
}
}
이러한 Mockito의 기능들을 활용하면 아래와 같은 장점이 있다:
- 외부 의존성 없이 테스트 가능
- 테스트 실행 속도 향상
- 다양한 시나리오 테스트 가능
- 테스트 코드의 가독성 향상
'Programing > Spring' 카테고리의 다른 글
| 상속매핑 전략과 선택 가이드 (0) | 2025.06.10 |
|---|---|
| 테스트 코드 mock()과 ReflectionTestUtils (0) | 2025.06.09 |
| API 로깅 Interceptor VS AOP (1) | 2025.06.05 |
| N+1 문제와 페치 조인 적용해 해결하기 (1) | 2025.06.02 |
| 좋아요 기능과 동시성 문제? (0) | 2025.06.02 |