Dummy, Fake, Stub, Spy, Mock
실제 객체를 대신해서 테스팅에서 사용하는 모든 방법을 일컬여 호칭하는 것이다.
(영화 촬영시 위험한 역활을 대신하는 스턴트 더블에서 비롯되었다.)
예를 들면 네트워크 API를 통해 어떤 정보를 받아서 수행하는 로직을 테스트 한다고 할때, 실제 네트워크 API를 그대로 사용하면, 테스팅은 네트워크 연결에 영향을 받을것이고, 항상 같은 조건에서 테스팅되어야 하는 조건을 지키지 못한다. ( 속도, 비효율적은 차치 하더라도 )
실제 객체를 사용하기 어렵고 모호한때 대신해 줄수 있는 객체를 만들어 테스트를 수행하도록 돕는다.
각 용어에 대해 정리했다.
이 글은 Martin Fowler의 Mocks Aren't Stubs 의 글의 내용을 참고해서 정리한 것이다.
(*원문에서 아래 의 정의는 Gerard Meszaros의 책을 기준으로 작성했다고 언급된다. )
객체는 전달되지만 사용되지 않는 객체이다.
예를 들면 함수 파라매터에 전달되는 빈 객체 등이 있다.
동작하는 구현을 가지고 있지만 실제 프로덕션에는 적합하지 않은( 혹은 동일하지 않은) 객체이다. 단순화된 버전의 동작을 제공하기도 한다.
예를 들어 인메모리 데이터 베이스가 있다.
관련 링크
작성해본 예제
테스트에서 호출된 요청에 대해 미리 준비해둔 결과를 제공한다.
테스트를 위해 프로그래밍된 내용이외에는 응답하지 않는다.
작성해본 예제
Stub 의 역활을 가지면서 호출된 내용에 대해 약간의 정보를 기록한다.
테스트에서 확인하기 위한 정보이다.
예를 들면, 메일링 서비스에서 발송된 메일의 갯수를 기록.
호출에 대한 기대를 명세하고, 해당 내용에 따라 동작하도록 프로그래밍 된 객체이다.
다른 개발환경에서는 Mock 프레임워크들이 존재하는데 XCode 에서 사용할수 있는 mock 프레임워크는 아직 보지 못했다. 직접 만들어서 써야한다.
Mock 객체를 만드는걸 도와주는 XCode 플러그인등은 존재한다.
Dart 언어 Mockito 패키지 의 예제를 발췌
Mock 은 exercise 단계에서 다른 Test Double 과 마찬가지로 동작한다.
기본적으로 Test Double은 테스트 객체가 다른 협업 객체와 메시징 할수 있도록 돕는것이 목적이니까.
Mock 은 setup 과 verify 에서 다른 Test Double과 다르다.
Mock 을 사용하면 구현부와 결합되는 부분이 많아진다.
위의 dart 예제에서 처럼 eatFood 에 응답을 명세 하는 과정을 보면 매우 구체적으로 메서드 명과 인자값이 어떻게 전달되어질지 지정한다.
이렇게 구현부와 결합되어있을때 리펙토링시 방해요소가 된다.
예를들어 함수의 인자명을 바꾸거나, 순서를 바꾸는 등의 리펙토링이 수행되면 테스트도 수정되어야 한다.
Xcode 에서 Mock 을 구현하는 방법은 여러가지가 있겠지만 메서드 명으로 구현하는 jMock 처럼 작성해봤다.
(verify 도 없고 argument 를 통한 명세를 할수도 없지만... 일단은)
Mock 을 사용했을때에 장점도 분명히 있다.
작성하기 나름이겟지만 테스트 코드 준비단계가 협력객체의 동작을 드러난다.
이부분은 장점이자 단점이기도 한것 같다.
마틴파울러는 본문에서 "캐시 히트상황" 등을 예로 들기도 했다.
별첨 1
MSDN에서는 fake 를 stub 과 mock 객체를 설명하는데 사용되는 용어로 설명한다.
마치며.
개발에서 쓰이는 용어를 잘 이해하는 것은 매우 중요하다. ( 테스트 만이 아닌 전체적으로 )
다른 사람(개발자)과 이야기를 나눌때, 같은 개념으로 용어를 이해해야 하기 때문이다.
마틴파울러의 글과 MSDN에서도 Mock 과 Stub 에 대해서 많이 오해되고 잘못 사용되는 것에 대해서 언급하고 있다. 어찌보면 매우 비슷하기 때문이 아닐까 싶기도 하다. (특히 행동검증을 하는 spy 객체와 비교될때)
상황에 따라 사용할수 있는 위와 같은 Test Double들을 통해, 더 나은 테스트를 작성할수 있었으면 좋겠다.