2020-12-5 백기선님 더자바 테스트(3) 강의정리 Mockito
Mockito
-
Mock : 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 객체의 행동을 관리하는 객체
- Mockito : Mock 객체를 쉽게 만들고 관리하고 검증할 수 있는 방법을 검증
- Spring-boot-starter-test 의존성을 추가하면 Mockito가 자동으로 들어온다.
- 없다면 의존성에 mockito-core, mockito-junit-jupiter를 추가하면 된다.
- Mock을 만드는 방법, Mock이 어떻게 동작해야하는지 설정, Mock의 행동을 검증하는 방법 3가지를 통해 테스트를 쉽게 검증할 수 있다.
Mock 객체 만들기
-
테스트할때 구현체는 없지만 의존성이 있는경우에 Mock을 만들기 좋다.
-
// Mock을 직접 만들기 class StudyServiceTest { @Test void createStudyService() { MemberService memberService = mock(MemberService.class); StudyRepository studyRepository = mock(StudyRepository.class); StudyService studyService = new StudyService(memberService, studyRepository); } } // @Mock 어노테이션을 활용 @ExtendWith(MockitoExtension.class) class StudyServiceTest { @Mock MemberService memberService; @Mock StudyRepository studyRepository; @Test void createStudyService() { StudyService studyService = new StudyService(memberService, studyRepository); assertNotNull(studyService); } }
// Mock을 특정 테스트에서만 쓰고 싶을때. @Test @DisplayName(“Mock을 특정 테스트에서만 사용하고 싶을때”) void createMockSpecificTest(@Mock MemberService memberService, @Mock StudyRepository studyRepository) { StudyService studyService = new StudyService(memberService, studyRepository); assertNotNull(studyService); }
- @Mock을 사용하면 @ExtendWith을 이용하여 MociktoExtension.class를 등록해야한다.
- 특정 테스트에서만 Mock을 쓰고 싶을때는 Mock객체를 테스트메서드 인자로 전달할 수 있다.
### Stubbing
- 모든 Mock객체
- Null을 리턴
- Primitive타입은 기본 Primitive
- 컬렉션은 비어있는 컬렉션
- void는 예외를 던지지 않고 아무일도 하지 않는다.
- Stubbing은 Mock객체가 특정 매개변수를 받아 특정값을 리턴하거나 예외를 던지도록할 수 있다.
- ```java
@Test
void createStudyService() {
StudyService studyService = new StudyService(memberService, studyRepository);
Member member = new Member();
member.setEmail("jimmy@email.com");
member.setId(1L);
when(memberService.findById(any())).thenReturn(Optional.of(member));
Optional<Member> findMember = memberService.findById(1L);
assertEquals("jimmy@email.com", findMember.get().getEmail());
assertEquals("jimmy@email.com", memberService.findById(2L).get().getEmail());
assertEquals(1L, findMember.get().getId());
doThrow(new IllegalArgumentException()).when(memberService).validate(2L);
assertThrows(IllegalArgumentException.class, () -> {
memberService.validate(2L);
});
Study study = new Study(10, "java");
studyService.createStudy(1L, study);
assertNotNull(studyService);
}
@Test
@DisplayName("예외에 대한 테스트")
void exception_test() {
StudyService studyService = new StudyService(memberService, studyRepository);
Member member = new Member();
member.setEmail("jimmy@email.com");
member.setId(1L);
// 첫번째 호출은 Optional<Member>, 두번째 호출은 RuntimeException, 세번째 호출은 Empty
when(memberService.findById(any()))
.thenReturn(Optional.of(member))
.thenThrow(new RuntimeException())
.thenReturn(Optional.empty());
Optional<Member> findMember = memberService.findById(1L);
assertEquals("jimmy@email.com", findMember.get().getEmail());
assertThrows(RuntimeException.class, () -> {
memberService.findById(1L);
});
assertEquals(Optional.empty(), memberService.findById(1L));
}
@Test
@DisplayName("notify Test")
void notifyTest(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member(1L, "jimmy@email.com");
Study study = new Study(10, "test");
when(memberService.findById(1L)).thenReturn(Optional.of(member));
when(studyRepository.save(study)).thenReturn(study);
studyService.createStudy(1L, study);
assertEquals(member, study.getOwner());
verify(memberService, times(1)).notify(study);
}
- when()을 이용하여 특정 메서드의 특정 파라미터가 호출됬을때 특정 객체가 리턴되도록 설정할 수 있다.
- any()는 ArgumentMatchers 클래스의 메서드로 anyObject(), anyBoolean(), matches() 등을 통해 다양한 파라미터를 받게할 수 있다.
Written on December 8, 2020