Mock을 이용한 TDD

바퀴달린 개발자·2021년 11월 24일
0

TDD

목록 보기
3/3

Mock 객체

  • Mock 이란, 조각하기 쉬운 재료를 이용해 추후 만들어질 제품의 외양을 흉내 낸 모조품이다.
  • 이와 같이, 모듈의 겉모양이 실제 모듈과 비슷하게 보이도록 만든 가짜 객체를 Mock 객체라고 한다.
  • 의존성이 걸쳐져 있을 때, Mock을 사용한다.

테스트 더블

  • Mock에 대한 기본적인 분류 개념이다.

쿠폰 다운로드 예제

유저 ID를 지군으로 신규 유저 객체 생성
-> 현재 쿠폰 확인
-> 신규 쿠폰 받기
-> 유저의 보유 쿠폰 개수 확인

더미 객체

  • 단지 인스턴스화된 객체가 필요할 뿐 해당 객체의 기능까지는 필요하지 않은 경우에 사용한다.
  • 호출 시엔 예외를 발생시키게 만들어 놓아야한다.

테스트 스텁

  • 만약 함수가 리턴값이 필요할 때 우리는 더미 객체보다 더 발전된 객체가 있어야 한다. 그런 기능을 하는 객체를 테스트 스텁이라고 한다.
  • 즉, 더미 객체가 마치 실제로 동작하는 것처럼 보이게 만든 객체다.

페이크 객체

  • 페이크는 여러 개의 인스턴스를 대표할 수 있는 경우이거나, 좀 더 복잡한 구현이 들어가 있는 객체를 지칭한다.

Mockito

차별점

  1. 테스트 그 자체에 집중한다.
    테스트의 행위와 반응에만 집중해서 테스트 메소드를 작성할 수 있게 한다.
  2. 테스트 스텁을 만드는 것과 검증을 분리시켰다.
  3. Mock 만드는 방법을 단일화했다.
  4. 테스트 스텁을 만들기 쉽다.
  5. API가 간단하다.
  6. 프레임워크가 지원해주지 않으면 안 되는 코드를 최대한 배제했따.
  7. 실패 시에 발생하는 에러추적이 깔끔하다.

기본 사용법

  • stub 작성과 verify가 중심을 이룬다.

<순서>
1. CreateMock
인터페이스에 해당하는 Mock 객체를 만든다.
2. Stub
테스트에 필요한 Mock 객체의 동작을 지정한다.
3. Exercise
테스트 메소드 내에서 Mock 객체를 사용한다.
4. Verify
메소드가 예상대로 호출됐는지 검증한다.

1. Mock 객체 만들기

import static org.mockito.Mockito.*;

List MockedList = mock(List.class);

2. 예상값 지정

Mockito는 테스트를 수행하고 결과를 보자의 개념이다. 그래서 예상값 지정 부분이 없다.

3. 테스트에 사용할 스텁 만들기

when(Mock_객체의_메소드).thenReturn(리턴값);
when(Mock_객체의_메소드).thenThrow(예외);

예제

// Stub 만들기
when (mockedList.get(0)).thenReturn("item");
when (mockedList.size()).thenReturn(1); 
when(mockedList.get(1)).thenThrow(new RuntimeException());

4. 검증

verify(Mock_객체).Mock_객체의_메소드;
verify(Mock_객체, 호출횟수지정_메소드).Mock_객체의_메소드;

해당 동작을 했는지 확인한다.

예제

verify (mockedList).add("item"); 
verify(mockedList, times(1)).add("item");
verify(mockedList, times(2)).add(box); 
verify(mockedList, never()).add(car);
verify(mockedList, atLeastOnce()).removeAll(); 
verify(mockedList, atLeast(2)).size(); 
verify(mockedList, atMost(5)).add(box);

argument matcher

erify(mockedList, times(5)).add( any() );

: 어떤 객체가 해당 메소드의 인자로 와도 무방하고, 대신 행동만 성공하고 싶을 때 사용한다.
1. any
2. anyInteger, anyBoolean
3. anyCollection, anyCollectionOf
4. argThat(HamcrestMatcher)
5. eq

등등..

순서 검증

List firstMock = mock(List.class); 
List secondMock = mock(List.class);
firstMock.add("item1"); 
secondMock.add("item2");
InOrder inOrder = inOrder(firstMock, secondMock); inOrder.verify(firstMock).add("item1"); inOrder.verify(secondMock).add("item2");

Mockito의 특징적인 기능

void 메소드를 Stub으로 만들기

  • void method는 리턴할 내용이 없어 stub으로 만들일이 없다. 하지만 예외가 발생하는 경우 doThrow로 구현할 수 있다.
doThrow(new RuntimeException()).when(mockList).clear();

콜백으로 Stub 만들기: thenAnswer

  • TDD 에서 권장하는 방식은 아님

실제 객체를 Stub으로 만들기: SPY

  • Mockito는 실 객체도 Mock으로 만들 수 있다.
  • Mockito의 저자는 spy 기능을 쓰게 된다면, 뭔가 잘못된 코드를 건드리고 있다는 증가라고 말한다.
ArrayList<String> realList = new ArrayList<String>(); 
realList.add("Hello"); 
System.out.println(realList.get(0));
List mockedList = spy( realList );

똑똑한 NULL 처리 : SMART NULLS

SMART NULLS의 규칙
1. 기본형 래퍼 클래스는 해당 기본형 값으로 바꾼다.
2. String은 ""로 바꾼다.
3. 배열은 크기 0인 기본 배열 객체로 만들어준다.
4. Collection 계열의 빈 Collection 객체로 만든다.

행위 주도 개발(BDD) 스타일 지원

  • given when then 식의 BDD 스타일로 테스트 케이스 작성할 수 있게 지원해준다.
import static org.mockito.BDDMockito.*;

// given
given(seller.askForBread()).willReturn(new Bread());
// when
Goods goods = shop.buyBread();
// then
assertThat(goods, containBread());

0개의 댓글