| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- Python
- CS
- 문자열
- 스프링
- 백준
- proxy
- Reflection
- Junit5
- 운영체제
- 모던자바
- 스프링 시큐리티
- 알고리즘
- java
- 모던 자바 인 액션
- spring security
- 리플렉션
- Deadlock
- 프록시
- OS
- 객체지향
- MST
- 다이나믹 프록시
- BOJ
- 자바
- 최소 신장 트리
- Spring
- test
- 파이썬
- redis
- 약수
Archives
- Today
- Total
Dev 달팽이 @_''
Java - Mockito 본문
Java - Mockito

Mock
- 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 그 객체의 행동을 관리하는 객체
Mockito
- 단위 테스트를 위한 Java mocking framework
Mockito Maven
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
- 스프링 부트 2.2+ 프로젝트에서는 자동으로 Mockito를 추가해준다.
- Mock을 활용한 테스트를 쉽게 하는 방법
- Mock을 만드는방법
- Mock이 어떻게 동작해야 하는지 관리하는 방법
- Mock의 행동을 검증하는 방법
- 자세한 내용은 Mockito 레퍼런스 참고
Mock 객체 만들기
- Mockito.mock() 메소드로 만드는 방법
@Test
void createStudyService(){
MemberService memberService = mock(MemberService.class);
StudyRepository studyRepository = mock(StudyRepository.class);
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
}
- @Mock 애노테이션으로 만드는 방법
- JUnit 5 extension으로 MockitoExtension을 사용해야 한다.(@ExtendWith)
- 필드
- 메소드 매개변수
- 필드
@ExtendWith(MockitoExtension.class)
public class StudyServiceTest {
@Mock MemberService memberService;
@Mock StudyRepository studyRepository;
@Test
void createStudyService(){
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
}
}
- 메소드 매개변수
@ExtendWith(MockitoExtension.class)
public class StudyServiceTest {
@Test
void createStudyService(@Mock MemberService memberService, @Mock StudyRepository studyRepository){
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
}
}
Mock 객체 Stubbing
- Stubbing
- 모의 객체 생성 및 모의 객체의 동작을 지정하는 것
- 모든 Mock 객체의 행동
- Null을 리턴(Optional 타입은 Optional.empty 리턴)
- Primitive 타입은 기본 Primitive 값
- 콜렉션은 비어있는 콜렉션
- void 메소드는 예외를 던지지 않고 아무런 일도 발생하지 않음
- Mock 객체 조작
- 특정한 매개변수를 받은 경우 특정한 값을 리턴하거나 예외를 던지도록 만들 수 있다.
- void 메소드 특정 매개변수를 받거나 호출된 경우 예외를 발생 시킬 수 있다.
- 메소드가 동일한 매개변수로 여러번 호출될 때 각기 다르게 행동하도록 조작할 수 있다.
@Test
void createStudyServiceWithAnno(@Mock MemberService memberService, @Mock StudyRepository studyRepository){
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("jdb4497@gmail.com");
//파라미터가 중요함
when(memberService.findById(1L))
.thenReturn(Optional.of(member));
//파라미터가 아무거나여도 됨
// when(memberService.findById(any()))
// .thenReturn(Optional.of(member));
Study study = new Study(10,"java");
Optional<Member> findById = memberService.findById(1L);
assertEquals("jdb4497@gmail.com",findById.get().getEmail());
// studyService.createNewStudy(1L,study);
doThrow(new IllegalArgumentException()).when(memberService).validate(1L);
assertThrows(IllegalArgumentException.class, ()->{
memberService.validate(1L);
});
memberService.validate(2L);
}
- when(memberService.findById(1L)).thenReturn(Optional.of(member));
- memberService 객체의 findById(1L)이 실행되면 member를 리턴한다.
- 매개변수가 중요함.(매개변수가 1L일 때만 체크)
- when(memberService.findById(any())).thenReturn(Optional.of(member));
- memberService 객체의 findById가 실행되면 member를 리턴한다.
- 매개변수가 아무거나여도 됨
- doThrow(new IllegalArgumentException()).when(memberService).validate(1L);
- memberService 객체의 validate(1L)이 실행되면 IlleagalArgumentException을 던진다.
Mock 객체 확인
- Mock 객체가 어떻게 사용 됐는지 확인
- 특정 메소드가 특정 매개변수로 몇번 호출 되었는지, 최소 한번은 호출 됐는지, 전혀 호출되지 않았는지 확인
- 어떤 순서대로 호출했는지 확인
- 특정 시간 이내에 호출됐는지 확인
- 특정 시점 이후에 아무 일도 벌어지지 않았는지 확인
- 특정 메소드가 특정 매개변수로 몇번 호출 되었는지, 최소 한번은 호출 됐는지, 전혀 호출되지 않았는지 확인
@Test
void createNewStudy(@Mock MemberService memberService,@Mock StudyRepository studyRepository){
StudyService studyService = new StudyService(memberService,studyRepository);
Member member = new Member();
member.setEmail("jdb4497@gmail.com");
member.setId(1L);
Study study = new Study(10,"테스트");
when(memberService.findById(1L))
.thenReturn(Optional.of(member));
when(studyRepository.save(study))
.thenReturn(study);
studyService.createNewStudy(1L,study);
assertNotNull(study.getOwnerId());
assertEquals(member.getId(),study.getOwnerId());
verify(memberService,times(1)).notify(study);
verify(memberService,times(1)).notify(member);
verify(memberService, never()).validate(any());
}
- verify(memberService, times(1)).notify(study);
- memberService의 notify(study) 함수가 1번 호출됐는지 확인한다.
- verify(memberService, never()).validate(any());
- memberService의 validate 함수가 한번도 호출되지 않았는지 확인한다.
- 어떤 순서대로 호출했는지 확인
@Test
void createNewStudy(@Mock MemberService memberService,@Mock StudyRepository studyRepository){
StudyService studyService = new StudyService(memberService,studyRepository);
Member member = new Member();
member.setEmail("jdb4497@gmail.com");
member.setId(1L);
Study study = new Study(10,"테스트");
when(memberService.findById(1L))
.thenReturn(Optional.of(member));
when(studyRepository.save(study))
.thenReturn(study);
studyService.createNewStudy(1L,study);
assertNotNull(study.getOwnerId());
assertEquals(member.getId(),study.getOwnerId());
InOrder inOrder = inOrder(memberService);
inOrder.verify(memberService).notify(study);
inOrder.verify(memberService).notify(member);
}
- InOrder(memberService);
- memberService에서 실행되는 함수의 순서를 확인한다.
- notify(study)가 notify(member) 보다 먼저 실행되는지 확인한다.
- 특정 시점 이후에 아무 일도 벌어지지 않았는지 확인
@Test
void createNewStudy(@Mock MemberService memberService,@Mock StudyRepository studyRepository){
StudyService studyService = new StudyService(memberService,studyRepository);
Member member = new Member();
member.setEmail("jdb4497@gmail.com");
member.setId(1L);
Study study = new Study(10,"테스트");
when(memberService.findById(1L))
.thenReturn(Optional.of(member));
when(studyRepository.save(study))
.thenReturn(study);
studyService.createNewStudy(1L,study);
assertNotNull(study.getOwnerId());
assertEquals(member.getId(),study.getOwnerId());
verify(memberService,times(1)).notify(study);
verify(memberService,times(1)).notify(member);
verifyNoMoreInteractions(memberService);
}
- verifyNoMoreInteractions(memberService);
- memberService에서 더 이상 아무 일도 벌어지지 않았는지 확인한다.
Mockito BDD 스타일
- BDD(Behavior-Driven Development)
- TDD에서 파생된 개발 방법
- "이 클래스가 어떤 행위를 해야한다(should do something)"라는 식의 문장으로 작성
- 행위에 대한 테스트에 집중
- 행동에 대한 스펙
- Title
- Narrative
- As a / I want / so that
- Acceptance critera
- Given / When / Then
- Mockito는 BddMockito라는 클래스를 통하여 BDD 스타일의 API를 제공
- 기존 Mockito
@Test
void createNewStudy(@Mock MemberService memberService,@Mock StudyRepository studyRepository){
// Given
StudyService studyService = new StudyService(memberService,studyRepository);
Member member = new Member();
member.setEmail("jdb4497@gmail.com");
member.setId(1L);
Study study = new Study(10,"테스트");
when(memberService.findById(1L)).thenReturn(Optional.of(member));
when(studyRepository.save(study)).thenReturn(study);
// When
studyService.createNewStudy(1L,study);
// Then
assertEquals(member.getId(),study.getOwnerId());
verify(memberService,times(1)).notify(member);
verify(memberService,times(1)).notify(study);
verifyNoMoreInteractions(memberService);
}
- 기존 Mockito에서는 Given에 when이 들어가있어 혼동할 가능성이 있음.
- 기존 Mockito에서 when을 given으로 verify를 then으로 바꾸면 됨.(given과 then은 BDDMockito에 포함)
- BDDMockito
@Test
void createNewStudyBDD(@Mock MemberService memberService,@Mock StudyRepository studyRepository){
// Given
StudyService studyService = new StudyService(memberService,studyRepository);
Member member = new Member();
member.setEmail("jdb4497@gmail.com");
member.setId(1L);
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.getId(),study.getOwnerId());
then(memberService).should(times(1)).notify(member);
then(memberService).should(times(1)).notify(study);
then(memberService).shouldHaveNoMoreInteractions();
}
- when이 given으로 thenReturn이 willReturn으로 변함.
- verify가 then으로 바뀌고 should이 추가.
'Java&Spring > 더 자바, 어플리케이션을 테스트하는 다양한 방법' 카테고리의 다른 글
| Java - JUnit 5 테스트 반복 (0) | 2022.01.11 |
|---|---|
| Java - JUnit 5 (0) | 2022.01.11 |