Mockito 사용하기2
1. Mock 객체 확인
1-1. 특정 메서드 동작 및 호출 횟수 확인
- Mockito의 verify() 메서드를 통해 특정 메서드가 몇번 실행됬는지 확인할 수 있다.
public class StudyService {
public Study createNewStudy(Long memberId, Study study) {
Optional<Member> member = memberService.findById(memberId);
study.setOwnerId(memberId);
Study newStudy = repository.save(study);
//memberService.notify(newStudy);
return repository.save(study);
}
...
}
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void stubbing(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("[email protected]");
Study study = new Study(10, "테스트");
Mockito.when(memberService.findById(1L)).thenReturn(Optional.of(member));
Mockito.when(studyRepository.save(study)).thenReturn(study);
studyService.createNewStudy(1L, study);
assertNotNull(study.getOwnerId());
assertEquals(member.getId(), study.getOwnerId());
Mockito.verify(memberService, Mockito.times(1)).notify(study); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.never()).validate(Mockito.any()); // validate 메서드는 호출되지 않길 기대
}
}
public class StudyService {
public Study createNewStudy(Long memberId, Study study) {
Optional<Member> member = memberService.findById(memberId);
study.setOwnerId(memberId);
Study newStudy = repository.save(study);
//memberService.notify(newStudy);
return repository.save(study);
}
...
}
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void stubbing(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("[email protected]");
Study study = new Study(10, "테스트");
Mockito.when(memberService.findById(1L)).thenReturn(Optional.of(member));
Mockito.when(studyRepository.save(study)).thenReturn(study);
studyService.createNewStudy(1L, study);
assertNotNull(study.getOwnerId());
assertEquals(member.getId(), study.getOwnerId());
Mockito.verify(memberService, Mockito.times(1)).notify(study); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.never()).validate(Mockito.any()); // validate 메서드는 호출되지 않길 기대
}
}
-
테스트코드에 맨 마지막줄을 보면 memberService의 notify() 메서드가 1번 호출되기를 기대했지만 주석처리 해놓았기 때문에 notify()메서드는 동작하지 않았고 에러가 난다.
-
또한 never() 메서드를 이용해 메서드가 호출되지 않았는지 확인할 수 있다.
1-2. 호출 순서 확인
public class StudyService {
private final MemberService memberService;
private final StudyRepository repository;
...
public Study createNewStudy(Long memberId, Study study) {
Optional<Member> member = memberService.findById(memberId);
study.setOwnerId(memberId);
Study newStudy = repository.save(study);
memberService.notify(newStudy);
memberService.notify(member.get());
return repository.save(study);
}
}
- 새 스터디를 만들었다는 notify() 메서드 호출 후, 회원에게 알리는 notify() 메서드를 호출
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void stubbing(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
...
InOrder inOrder = Mockito.inOrder(memberService);
//성공
inOrder.verify(memberService).notify(study);
inOrder.verify(memberService).notify(member);
//실패
inOrder.verify(memberService).notify(member);
inOrder.verify(memberService).notify(study);
}
}
- Inorder를 먼저 생성해 준 후
실제로 호출되는 메서드 순서대로 verify()를 하면 테스트는 성공한다.
1-3. 특정 시점에 아무일도 일어나지 않았는지 확인
- 즉 특정 메서드를 호출한 후에 아무 메서드도 호출되지 않았는지 확인할 수 있다.
public class StudyService {
private final MemberService memberService;
private final StudyRepository repository;
...
public Study createNewStudy(Long memberId, Study study) {
Optional<Member> member = memberService.findById(memberId);
study.setOwnerId(memberId);
Study newStudy = repository.save(study);
memberService.notify(newStudy);
memberService.notify(member.get());
return repository.save(study);
}
}
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void stubbing(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
...
//실패
Mockito.verify(memberService, Mockito.times(1)).notify(study); // notify 메서드가 한번 호출하기를 기대
Mockito.verifyNoMoreInteractions(memberService); // 실패 아래 notify()메서드가 동작하므로
Mockito.verify(memberService, Mockito.times(1)).notify(member); // notify 메서드가 한번 호출하기를 기대
//성공
Mockito.verify(memberService, Mockito.times(1)).notify(study); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.times(1)).notify(member); // notify 메서드가 한번 호출하기를 기대
Mockito.verifyNoMoreInteractions(memberService);
}
}
- verifyNoMoreInteractions() 메서드를 이용하면 된다.
2. Mockito BDD 스타일 API
2-1. BDD
- BDD란?
- Behaviour Driven Development로 행위 주도 개발이라고 한다. 애플리케이션이 어떻게 행동해야 하는지에 대한 공통된 이해를 구성하는 방법으로 TDD에서 창안되었다.
- 행동에 대한 스펙
- Narrative (행동에대한 설명을 정의할 때)
- As a / i want / so that
- Acceptance criteria
- Given / When / Then
- 어떤 상황이 주어졌을 때 / 어떤 행동을 했을 때 / 이런 결과가 나와야 한다.
2-2. BDD스타일 API 적용
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void stubbing(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
//Given
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("[email protected]");
Study study = new Study(10, "테스트");
Mockito.when(memberService.findById(1L)).thenReturn(Optional.of(member));
Mockito.when(studyRepository.save(study)).thenReturn(study);
//when
studyService.createNewStudy(1L, study);
//then
Mockito.verify(memberService, Mockito.times(1)).notify(study); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.times(1)).notify(member); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.never()).validate(Mockito.any()); // validate 메서드는 호출되지 않길 기대
Mockito.verifyNoMoreInteractions(memberService);
}
}
-
이처럼 Given, When, Then으로 나눌 수 있다.
-
이를 위한 라이브러리 JBehave같은 것들도 지원하는데 굳이 사용할필요까진 없고
Mockito에서도 BDD를 위해 지원하는 기능들이 있다.
-
예로 위에서 보면 Mockito.when() 을 사용하는 부분은 Given에 해당하지만 API가 when이라서
조금 어울리지 않는다. 따라서 when() 대신 given()이라는 API를, verify() 대신 then() 등을 제공하고 있다.
Ref
- https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
- https://www.inflearn.com/course/the-java-application-test
Author And Source
이 문제에 관하여(Mockito 사용하기2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@znftm97/Mockito-사용하기2
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
- Behaviour Driven Development로 행위 주도 개발이라고 한다. 애플리케이션이 어떻게 행동해야 하는지에 대한 공통된 이해를 구성하는 방법으로 TDD에서 창안되었다.
- Narrative (행동에대한 설명을 정의할 때)
- As a / i want / so that
- Acceptance criteria
- Given / When / Then
- 어떤 상황이 주어졌을 때 / 어떤 행동을 했을 때 / 이런 결과가 나와야 한다.
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void stubbing(@Mock MemberService memberService, @Mock StudyRepository studyRepository) {
//Given
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("[email protected]");
Study study = new Study(10, "테스트");
Mockito.when(memberService.findById(1L)).thenReturn(Optional.of(member));
Mockito.when(studyRepository.save(study)).thenReturn(study);
//when
studyService.createNewStudy(1L, study);
//then
Mockito.verify(memberService, Mockito.times(1)).notify(study); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.times(1)).notify(member); // notify 메서드가 한번 호출하기를 기대
Mockito.verify(memberService, Mockito.never()).validate(Mockito.any()); // validate 메서드는 호출되지 않길 기대
Mockito.verifyNoMoreInteractions(memberService);
}
}
이처럼 Given, When, Then으로 나눌 수 있다.
이를 위한 라이브러리 JBehave같은 것들도 지원하는데 굳이 사용할필요까진 없고
Mockito에서도 BDD를 위해 지원하는 기능들이 있다.
예로 위에서 보면 Mockito.when() 을 사용하는 부분은 Given에 해당하지만 API가 when이라서
조금 어울리지 않는다. 따라서 when() 대신 given()이라는 API를, verify() 대신 then() 등을 제공하고 있다.
- https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
- https://www.inflearn.com/course/the-java-application-test
Author And Source
이 문제에 관하여(Mockito 사용하기2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@znftm97/Mockito-사용하기2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)