Mockito 란?
- Mock: 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 그 객체의 행동을 관리하는 객체다.
- Mockito: Mock 객체를 쉽게 만들고 관리하고 검증할 수 있는 방법을 제공한다.
- 테스트를 작성하는 자바 개발자 50%+ 사용하는 Mock 프레임워크다.
Mock 객체 생성
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Mock
MemberService memberService;
@Mock
StudyRepository studyRepository;
@Test
void createStudyService() {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
}
}
- @Mock 을 사용해서 위와 같이 Mock 객체를 생성할 수 있다.
@Test
void createStudyService(@Mock MemberService memberService,
@Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
}
- 위와 같이 매개변수에 설정해서 해당 메서드에만 적용시킬 수 있다.
Mock 객체 Stubbing
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void createNewStudy(@Mock MemberService memberService,
@Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("newleader95@gmail.com");
when(memberService.findById(any()))
.thenReturn(Optional.of(member))
.thenThrow(new RuntimeException())
.thenReturn(Optional.empty());
Optional<Member> byId = memberService.findById(1L);
assertEquals("newleader95@gmail.com", byId.get().getEmail());
assertThrows(RuntimeException.class, () -> {
memberService.findById(2L);
});
assertEquals(Optional.empty(), memberService.findById(3L));
}
}
- 특정한 매개변수를 받은 경우 특정한 값을 리턴하거나 예뢰를 던지도록 만들 수 있다.
- Void 메소드 특정 매개변수를 받거나 호출된 경우 예외를 발생 시킬 수 있다.
- 메소드가 동일한 매개변수로 여러번 호출될 때 각기 다르게 행동호도록 조작할 수도 있다.
Mock 객체 확인
- Mock 객체가 어떻게 사용이 됐는지 확인할 수 있다.
- 예시는 아래와 같다.
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Mock MemberService memberService;
@Mock StudyRepository studyRepository;
@Test
void createNewStudy() {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("newleader95@gmail.com");
Study study = new Study(10, "테스트");
when(memberService.findById(1L)).thenReturn(Optional.of(member));
when(studyRepository.save(study)).thenReturn(study);
studyService.createNewStudy(1L, study);
assertEquals(member, study.getOwner());
verify(memberService, times(1)).notify(study);
}
}
- 특정 메소드가 특정 매개변수로 몇번 호출 되었는지, 최소 한번은 호출 됐는지, 전혀 호출되지 않았는지 확인할 수 있다.
verify(memberService, times(1)).notify(study);
verify(memberService, times(1)).notify(member);
verify(memberService, never()).validate(any());
- 위와 같이 어떤 순서대로 호출했는지 확인할 수 있다.
- 이외에도 다양한 기능들을 확인할 수 있다.
Mockito BDD 스타일 API
- BDD : 애플리케이션이 어떻게 "행동"해야 하는지에 대한 공통된 이해를 구성하는 방법으로, TDD에서 창안됐다.
- Mockito는 BddMockito라는 클래스를 통해 BDD 스타일의 API를 제공한다.
- Given -> When -> Then
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Mock MemberService memberService;
@Mock StudyRepository studyRepository;
@Test
void createNewStudy() {
// Given
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("newleader95@gmail.com");
Study study = new Study(10, "테스트");
given(memberService.findById(1L)).willReturn(Optional.of(member));
given(studyRepository.save(study)).willReturn(study);
// When
studyService.createNewStudy(1L, study);
// Then
assertEquals(member, study.getOwner());
then(memberService).should(times(1)).notify(study);
then(memberService).shouldHaveNoMoreInteractions();
}
}
REFERENCES
- 백기선님의 더 자바, 애플리케이션을 테스트하는 다양한 방법