Mock 객체의 행동이란
- 리턴 값이 있는 메소드는 모두 Null 을 리턴하고 있다.
- Optional 타입인 경우 Optional.empty로 리턴
- Primitive 타입은 모두 Primitive 값을 따르고 있다.
- Ex. Boolean인 경우 'false' / Integer 혹은 Long인 경우 0
- Collection의 경우 모두 비어있는 Collection을 가지고 있다.
- Void 메소드의 경우 예외를 던지지 않고 아무 일도 발생하지 않는다.
Stubbing이란
- Mock 객체의 행동을 조작하는 것을 말한다.
- Mock객체의 when 메소드를 활용하여 Stubbing을 진행해보자.
- Ex. 리턴값이 있는 when 메소드 활용 1
StudyService
public Study createNewStudy(Long memberId, Study study) {
Optional<Member> member = memberService.findById(memberId);
study.setOwner(member.orElseThrow(() ->
new IllegalArgumentException("Member doesn't exist for id: '" + memberId + "'")));
return repository.save(study);
}
StudyServiceTest
@ExtendWith(MockitoExtension.class)
class StudyServiceTest {
@Test
void createStudyService(@Mock MemberService memberService,
@Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("jisu@email.com");
when(memberService.findById(1L)).thenReturn(Optional.of(member));
Study study = new Study(10, "java");
studyService.createNewStudy(1L, study);
}
}
Stubbing이 Mock 객체의 행동을 조작한다고 했습니다.
만약에 아이디가 1인 객체를 리턴해주었으면 좋겠다고 개발자가 Mock객체의 행동을 조작하고 싶을때 어떻게 하는지 알아 보겠습니다.
Member객체를 만듭니다. Member 객체를 만들어 Id에 1과 Email을 넣어줬습니다.
그 후의 when은 ~하면이라고 이해하면 쉽습니다. 아이디가 1인 member가 호출되면~ > thenReturn : 리턴해라
member는 Optional이기떄문에 member를 감싸줍니다.
그리고 Study가 호출될때 1L 은 파라미터로 StudyService클래스의 createNewStuidy 메소드의 memberService.findById(memberId)로 전달됩니다.
여기서 memberService는 위에서 만든 Mock 객체입니다.
저희는 when 절에 findById가 1이라는 값으로 호출되면 바로 위에서만든 Member객체가 리턴되도록 Stubbing을 해 놓은 것입니다.
그래서 studyService.createNewStudy에서 파라미터로 1L이 넘어가서 호출될때면 test코드에서 만든 Member객체가 리턴되게 됩니다.
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("jisu@email.com");
when(memberService.findById(1L)).thenReturn(Optional.of(member));
Optional<Member> findById = memberService.findById(1L);
assertEquals("jisu@email.com", findById.get().getEmail());
// Study study = new Study(10, "java");
// studyService.createNewStudy(1L, study);
![[Mockito] Mock 객체 Stubbing - StudyServiceTest [Mockito] Mock 객체 Stubbing - StudyServiceTest](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
그래서 위와같이 테스트해도 통과가 되는 모습입니다.
여기서 when(memberService.findById(2L)).thenReturn(Optional.of(member)); 2로 아이디로 넣는다면 테트스가 통과하지 못합니다.
여기서 ArgumentMatchers 라는게 있습니다. 조금더 범용적으로 작성할 수 있습니다.
ArgumentMatchers.any()를 하게 되면 어떤 파라미터를 넘겨주든 같은 객체가 리턴되게 됩니다.
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("jisu@email.com");
when(memberService.findById(any())).thenReturn(Optional.of(member));
assertEquals("jisu@email.com", memberService.findById(1L).get().getEmail());
assertEquals("jisu@email.com", memberService.findById(2L).get().getEmail());
![[Mockito] Mock 객체 Stubbing - StudyServiceTest [Mockito] Mock 객체 Stubbing - StudyServiceTest](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
그래서 테스트가 통과 되게 됩니다.
또 메소드가 동일한 매개변수로 여러번 호출 될 때 각기 다르게 행동하도록 조작할 수 도 있습니다.
@Test
void createStudyService(@Mock MemberService memberService,
@Mock StudyRepository studyRepository) {
StudyService studyService = new StudyService(memberService, studyRepository);
assertNotNull(studyService);
Member member = new Member();
member.setId(1L);
member.setEmail("jisu@email.com");
when(memberService.findById(any()))
.thenReturn(Optional.of(member))
.thenThrow(new RuntimeException())
.thenReturn(Optional.empty());
Optional<Member> byId = memberService.findById(1L);
assertEquals("jisu@email.com", byId.get().getEmail());
assertThrows(RuntimeException.class, () -> {
memberService.findById(2L);
});
assertEquals(Optional.empty(), memberService.findById(3L));
}
위와 같을떄 첫번째는 Optional로 member객체를 리턴하고 두번째는 예외, 세번째는 비어있는 값을 리턴하게 했습니다.
![[Mockito] Mock 객체 Stubbing - StudyServiceTest [Mockito] Mock 객체 Stubbing - StudyServiceTest](https://blog.kakaocdn.net/dn/KQ5Q5/btrI4VVOzb1/kL2t28yNxmWeG9lqvJwm7k/img.png)
테스트가 통과되는 모습입니다.
지금까지 Stubbing 하는 방법을 알아봤습니다.
'Spring Boot > Mockito' 카테고리의 다른 글
[Mockito] BDD 스타일 API + BDD (0) | 2022.08.07 |
---|---|
[Mockito] Verify(검증) (0) | 2022.08.07 |
[Mockito] Mockito 시작하기 (0) | 2022.08.07 |
[Mockito] Mockito (0) | 2022.08.07 |
댓글