진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 그 객체의 행동을 관리하는 객체.
테스트할 서비스 자체만 테스트하고, 서비스 이외의 부분은 mock으로 대체하여 본래 목적의 프로그램 테스트만 잘 동작하도록 설정한다.
mockito 문서보기: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
1) 인터페이스만 있고 구현되어있지 않는 경우, 일반적으로 직접 그 내용을 구현해야하지만 mock을 사용하면 코드를 간략하게 작성할 수 있다.
2) 외부 연동과 같이 통제가 안되는 서비스를 테스트 코드에 사용해야 할 때
mock을 사용하기 위해 가장 먼저 mock 객체를 만든다.
MemberService memberService = mock(MemeberService.class);
StudyRepository studyRepository = mock(StudyRepository.class);
//extend를 선언해주고
@ExtendWith(MockitoExtension.class)
class studyTest{
//1) 직접 선언할 수도 있고
@Mock MemberService memberService;
@Mock StudyRepository studyRepository;
//2) 또는 메소드 파라미터로 직접 넣어줄 수도 있다.
@Test void createStudyService(@Mock MemberService memberService,
@Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
}
}
모든 Mock 객체의 행동
Member member = new member();
member.setId(1L);
member.setEmail("tester@email.com")
//1L로 검색 시에만 리턴하는 시키도록 stubbing하거나
when(memberService.findById(1L)).thenReturn(Optional.of(member));
//인자를 any로 입력 시 항상 같은 객체를 리턴 subbing
when(memberService.findById(any())).thenReturn(Optional.of(member));
Study study = new Study(10, "java");
//stubbing 된 member가 리턴된다.
studyService.createNewStudy(1L, study)
//when 메소드의 thenThrow를 사용하거나
when(memberService.findById(1L)).thenThrow(new RuntimeException());
//doThrow를 사용
doThrow(new IllegalArgumentException()).when(memberService).validate(1L);
메소드가 동일한 매개변수로 여러 번 호출 될 때 각기 다르게 행동하도록 조작할 수 있다.
when(memberService.findById(any()))
.thenReturn(optional.of(member)) //#1
.thenThrow(new RuntimeException()) //#2
.thenReturn(Optional.empty()); //#3
//#1 호출
when(memberService.findById(1L)).thenReturn(Optional.of(member));
//#2 호출
when(memberService.findById(1L)).thenReturn(Optional.of(member));
//#3 호출
when(memberService.findById(1L)).thenReturn(Optional.of(member));
//1번 notify가 1번 호출했는지 확인
verify(memberService, times(1)).notify(study))
//validate가 실행 안됐는지 확인
verify(memberService, never()).validate(any());
💡 BDD - Behavior Driven Development
given, when, then형식으로 테스트를 할수 있도록 지원
@DisplayName("스터디가 생성되면 안내한다.")
@Test
void createStudy(){
//given (기존 when은 BDD스타일의 when과 햇갈리므로 given으로 변경)
when(memberService.findById(1L)).willReturn(Optional.of(member));
given(memberService.findById(1L)).willReturn(optional.of(member));
//when
studyService.createStudy(1L, study)
//then (verify를 then으로 변경)
then(memberService).should(times(1)).notify(study);
}
출처: 백기선님 인프런 강의 "더 자바, 애플리케이션을 테스트하는 다양한 방법"를 수강 후 정리한 내용임
https://www.inflearn.com/course/the-java-application-test/dashboard