Spring Boot/Mockito

[Mockito] Verify(검증)

수수한개발자 2022. 8. 7.
728x90

이번 포스팅에선 Mockito를 이용해 스터 빙한 메서드가 제대로 실행이 됐는지 확인해보는 메서드에 대해서 알아보겠습니다.

스터 빙한 메서드를 검증하는 방법

verify 메서드를 이용해서 스터 빙한 메서드가 실행됐는지, n번 실행됐는지, 실행이 초과되지 않았는지 등 다양하게 검증해볼 수 있습니다.

 

verify(T mock, VerificationMode mode)

 

위와 같은 형태로 쓰며 VerificationMode는 검증할 값을 정의하는 메서드입니다.

 

메소드명 설명 (테스트 내에서~)
times(n) 몇 번이 호출됐는지 검증
never 한 번도 호출되지 않았는지 검증
atLeastOne 최소 한 번은 호출됐는지 검증
atLeast(n) 최소 n 번이 호출됐는지 검증
atMostOnce 최대 한 번이 호출됐는지 검증
atMost(n) 최대 n 번이 호출됐는지 검증
calls(n) n번이 호출됐는지 검증 (InOrder랑 같이 사용해야 함)
only 해당 검증 메소드만 실행됐는지 검증
timeout(long mills) n ms 이상 걸리면 Fail 그리고 바로 검증 종료
after(long mills) n ms 이상 걸리는지 확인

timeout과 다르게 시간이 지나도 바로 검증 종료가 되지 않는다.
description 실패한 경우 나올 문구

 

예제

times(n) , never()

MemberService

 

public interface MemberService {

    Optional<Member> findById(Long memberId);

    void validate(Long memberId);

    void notify(Study newStudy);
}

 

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 + "'")));
    Study newStudy = repository.save(study);
    memberService.notify(newStudy);
    return repository.save(study);
}


StudyServiceTest

 

DisplayName("Verify")
@Test
void createStudyService3() {

    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, "테스트");
    when(studyRepository.save(study)).thenReturn(study);

    studyService.createNewStudy(1L, study);

    assertEquals(member, study.getOwner());
    verify(memberService, times(1)).notify(study);
}

StudyService에서 memberService.notify(study); 를 주석 처리하면 이 테스트는 times를 1로 주었기 때문에 1번 호출되어야 하지만 주석처리로 인해서 호출이 되지 않습니다. 

그래서 verify(memberService, times(1)). notify(study); 코드 때문에 위처럼 실패하게 됩니다.

 

그리고 위에서 사용하지 않는 memberService의 validate를 검증하면 다음과 같습니다.

verify(memberService, never()).validate(any());

never()를 사용하게 되면 사용하지 않는지를 검증하게 됩니다.

 

 

InOrder (순서 검증)

 

memberService

public interface MemberService {
   ...
    void notify(Member member);
}

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 + "'")));
    Study newStudy = repository.save(study);
    memberService.notify(newStudy);
    memberService.notify(member.get());
    return repository.save(study);
}

StudyServiceTest

verify(memberService, times(1)).notify(study);
verify(memberService, times(1)).notify(member);
verify(memberService, never()).validate(any());

InOrder inOrder = inOrder(memberService);
inOrder.verify(memberService).notify(study);
inOrder.verify(memberService).notify(member);

이런 식으로 위의 코드가 먼저 호출되는지 검증을 할 수 있게 됩니다.

 

verifyNoMoreInteractions(T mock)

- 선언한 verify 후 해당 mock을 실행하면 fail

 

StudyServiceTest

@DisplayName("Verify - verifyNoMoreInteractions")
@Test
void createStudyService5() {

    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, "테스트");
    when(studyRepository.save(study)).thenReturn(study);

    studyService.createNewStudy(1L, study);

    assertEquals(member, study.getOwner());
    verify(memberService, times(1)).notify(study);
    verifyNoMoreInteractions(memberService);
}

이 상태에서 memberService에서는 notify가 두 번 실행되기 때문에 테스트가 실패하게 됩니다.

728x90

'Spring Boot > Mockito' 카테고리의 다른 글

[Mockito] BDD 스타일 API + BDD  (0) 2022.08.07
[Mockito] Mock 객체 Stubbing  (0) 2022.08.07
[Mockito] Mockito 시작하기  (0) 2022.08.07
[Mockito] Mockito  (0) 2022.08.07

댓글