단위 테스트는 Service Layer의 비즈니스 로직만을 검증하는 것이므로, Repository와 Controller의 영향을 받지 않는 환경에서 테스트를 진행하여야 한다.
F - Fast: 테스트를 시도하는 것에 있어서 주춤되지 않을 만큼 빨라야 한다.
I - Independent: 객체의 상태, 메소드, 이전 테스트 상태, 다른 메소드의 결과에 의존해서는 안된다.
R - Repeatable: 어떤 환경에서도 같은 결과가 나올 수 있도록 반복 가능해야 한다.
S - Self-Validating: 모든 테스트는 pass 혹은 fail의 결과만 가지고 있어야 한다.
T - Timely: 실제 코드가 만들어지기 전에 테스트 되어야 한다. 실제 코드를 구현한 후 테스트 코드를 만들면, 테스트가 불가능하도록 실제 코드를 설계할지도 모른다.
자바에서 단위테스트를 하기 위해 Mock을 만들어주는 프레임워크
실제 객체를 만들어 사용하기에 시간, 비용등의 Cost가 높거나 혹은 객체 서로간의 의존성이 강해 구현이 힘들 경우 가짜 객체를 만들어 사용하는 방법
사용법: https://github.com/mockito/mockito/wiki/Mockito-features-in-Korean
@ExtendWith(MockitoExtension.class)
class SafetyInfoServiceTest {
@InjectMocks
private SafetyInfoServiceImpl safetyInfoService;
@Mock
private SafetyInfoRepository safetyInfoRepository;
@Mock
private UserRepository userRepository;
@Mock
private SafetyInfoQueryRepository safetyInfoQueryRepository;
final String userEmail = "test@gmail.com";
void setup(){
User user = User.builder().build();
given(userRepository.findByEmail(userEmail)).willReturn(Optional.of(user));
}
@Test
void findAllSafetyInfo() {
// given
setup();
List<FindSafetyInfoResDto> expected = new ArrayList<>();
given(safetyInfoQueryRepository.findAllWithUserId(any())).willReturn(expected);
// when
List<FindSafetyInfoResDto> response = safetyInfoService.findAllSafetyInfo(userEmail);
// then
assertThat(response).isEqualTo(expected);
}
}
SpringContainer를 로드하지 않고(=Spring에 의존하지 않음) 필요한 객체만 실행함 -> 매우 빠름!
- @Mock: 테스트에 '필요한' 가짜 객체
- @InjectMocks: 의존성 주입이 필요한 Mock 객체
@Mock으로 선언된 가짜 객체들을 의존한 @InjectMocks 객체를 생성!
메소드가 실행되었을 때의 테스트를 위한 상황을 설정
- a: Mocking 할 메소드
- b: 메소드의 파라미터
- c: 메소드를 수행했을 때 반환했다고 설정할 값
when: Mockito를 import
given: BDDMockito를 import
차이: BDD 방식을 코드에 도입할 때, 기존의 Mockito가 가독성을 해치기 때문에 이를 해결하기 위한 기능은 같지만 이름이 다른 클래스!