Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
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
Archives
Today
Total
관리 메뉴

개발자일기

Mockito를 이용한 Unit테스트 Mocking 본문

개발

Mockito를 이용한 Unit테스트 Mocking

ka0oll 2020. 3. 22. 15:24

Mockito

mockito란?

  • mock객체를 생성하여 stubbing하고 검증 할수 있도록 한다.

용어 정리

  • Stub : 테스트에서 호출된 요청에 대한 미리 준비해둔 결과를 제공

  • Mock : stub + 행동에 대한 검증을 위한것

  • Spy : 실제 구현체 + mock, 실제 구현체의 일부만 mocking 할수있는 기능 제공

시작하기

스프링 부트 2.2+ 프로젝트 생성시 spring-boot-starter-test에서 자동으로 Mockito 추가해 줌.
스프링 부트 쓰지 않는다면, 의존성 직접 추가.

<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>

Mock 생성

직접 생성

MemberService memberService = mock(MemberService.class);
StudyRepository studyRepository = mock(StudyRepository.class);

@Mock 애노테이션으로 만드는 방법

@ExtendWith(MockitoExtension.class)
class StudyServiceTest {

    @Mock MemberService memberService;

    @Mock StudyRepository studyRepository;
}

@ExtendWith(MockitoExtension.class)
class StudyServiceTest {

    @Test
    void createStudyService(@Mock MemberService memberService,
                            @Mock StudyRepository studyRepository) {
        StudyService studyService = new StudyService(memberService, studyRepository);
        assertNotNull(studyService);
    }

}

Mock객체 stubing

기본 행동

  • null리턴
  • primitive 기본값 리턴
  • 콜렉션은 비어있는 콜렉션
  • Void는 아무 액션이 없다.

조작

//You can mock concrete classes, not just interfaces
 LinkedList mockedList = mock(LinkedList.class);

 //stubbing
 when(mockedList.get(0)).thenReturn("first");
 when(mockedList.get(1)).thenThrow(new RuntimeException());

 //stubbing using built-in anyInt() argument matcher
 when(mockedList.get(anyInt())).thenReturn("element");

Mock객체 검증

호출 검증

//using mock
 mockedList.add("once");

 mockedList.add("twice");
 mockedList.add("twice");

 mockedList.add("three times");
 mockedList.add("three times");
 mockedList.add("three times");

 //following two verifications work exactly the same - times(1) is used by default
 verify(mockedList).add("once");
 verify(mockedList, times(1)).add("once");

 //exact number of invocations verification
 verify(mockedList, times(2)).add("twice");
 verify(mockedList, times(3)).add("three times");

 //verification using never(). never() is an alias to times(0)
 verify(mockedList, never()).add("never happened");

 //verification using atLeast()/atMost()
 verify(mockedList, atMostOnce()).add("once");
 verify(mockedList, atLeastOnce()).add("three times");
 verify(mockedList, atLeast(2)).add("three times");
 verify(mockedList, atMost(5)).add("three times");

순서 검증

// A. Single mock whose methods must be invoked in a particular order
 List singleMock = mock(List.class);

 //using a single mock
 singleMock.add("was added first");
 singleMock.add("was added second");

 //create an inOrder verifier for a single mock
 InOrder inOrder = inOrder(singleMock);

 //following will make sure that add is first called with "was added first", then with "was added second"
 inOrder.verify(singleMock).add("was added first");
 inOrder.verify(singleMock).add("was added second");

 // B. Multiple mocks that must be used in a particular order
 List firstMock = mock(List.class);
 List secondMock = mock(List.class);

 //using mocks
 firstMock.add("was called first");
 secondMock.add("was called second");

 //create inOrder object passing any mocks that need to be verified in order
 InOrder inOrder = inOrder(firstMock, secondMock);

 //following will make sure that firstMock was called before secondMock
 inOrder.verify(firstMock).add("was called first");
 inOrder.verify(secondMock).add("was called second");

 // Oh, and A + B can be mixed together at will

특정 시간 이내에 호출됐는지
Verification with timeout https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#verification_timeout

Mockito BDD style

BDD : Behaviour-Driven Development의 약자, 어플리케이션이 어떻게 "행동"해야 하는지에 대한 이해로, TDD에서 창안됨
행동에 대한 스펙

  • Title
  • Narrative : As a / I want / so that
  • Acceptance criteria : Given / When / Then

Mockito는 BDD에 대한 스펙 제공

  • 기존에 stubbing 할때 when은 BDD와 맞지 않음, BDD에서는 given임
    When -> Given
    given(memberService.findById(1L)).willReturn(Optional.of(member));
    given(studyRepository.save(study)).willReturn(study);
    

Verify -> Then
then(memberService).should(times(1)).notify(study);
then(memberService).shouldHaveNoMoreInteractions();

'개발' 카테고리의 다른 글

진정한 Rest Api란 무엇인가?  (0) 2020.03.28
Spring mvc NIO + webflux  (0) 2020.03.24
Spring의 핵심 및 기술  (0) 2020.03.21
도커를 이용한 테스트  (0) 2020.03.21
JUnit5을 이용한 단위테스트  (0) 2020.03.21
Comments