1 목과 테스트 취약성
- 테스트에서 목을 사용하는 것은 논란의 여지가 있다
- 목으로 인해 취약한 테스트, 즉 리팩터링 내성이 부족한 테스트를 초래하는 경우와 목 사용이 바람직한 경우를 살펴보자
- 그 전에 목과 스 텁의 개념에 대해서 알아보자
2 테스트 대역
- 테스트 대역은 모든 유형의 비운영용 가짜 의존성을 설명하는 포괄적인 용어다
- 테스트 대역의 주 목적은 테스트를 편리하게 하는 것이다
- 테스트 대역에는 더미, 스텁, 스파이, 목, 페이크라는 다섯가지가 있다
- 여러 유형에 겁먹을 수 있지만 실제로 목과 스텁의 두 가지 유형으로 나눌 수 있다
- 목은 스파이를 포함한다
- 스텁은 더미와 페이크를 포함한다
2.1 목과 스텁의 차이
- 목은 외부로 나가는 상호 작용을 모방하고 검사하는데 도움이 된다
- 스텁은 내부로 들어오는 상호 작용을 모방하는데 도움이 된다
3 목
- 목은 외부로 나가는 상호 작용을 모방하고 검사하는데 도움이 된다
- 반대로 스텁은 내부로 들어오는 상호 작용을 모방만 한다
- 이러한 상호 작용은 SUT가 상태를 변경하기 위한 의존성을 호출하는 것에 해당된다
- SUT의 의존성 호출로 해 당 의존성의 상태를 변경한다
- 예를 들면 이메일 발송은 SMTP 서버에 부작용(상태 변경)을 초래하는 상호 작용, 즉 외부로 나가는 상호작용 이다
- 목은 이러한 상호 작용을 모방하는 테스트 대역에 해당된다
- 목, 스파이는 목에 포함된다
3.1 스파이
- 스파이는 목과 같은 역할을 하지만 스파이는 수동으로 작성하는 반면 목은 목 프레임워크의 도움을 받아 생성된다
4 스텁
- 스텁은 내부로 들어오는 상호 작용을 모방하는데 도움이 된다
- 반대로 목은 목은 외부로 나가는 상호 작용을 모방하고 검사까지 한다
- 이러한 상호 작용은 SUT가 입력 데이터를 얻기 위한 의존성을 호출하는 것에 해당된다
- 예를 들면 데이터베이스에서 데이터를 검색하는 것은 내부로 들어오는 상호 작용이다
- 부작용을 일으키지 않는다
- 해당 테스트 대역은 스텁이다
- 스텁, 더미, 페이크는 스텁에 포함된다
4.1 더미
- 더미는 널 값이나 가짜 문자열과 같이 단순하고 하드코딩된 값이다
- SUT의 메서드 시그니처를 만족시키기 위해 사용하고 최종 결과를 만드는데 영향을 주지 않는다
4.2 스텁
- 시나리오마다 다른 값을 반환하게끔 구성할 수 있도록 필요한 것을 다 갖춘 완전한 의존성이다
4.3 페이크
- 페이크는 대다수의 목적에 부합하는 스텁과 같다
- 차이점은 생성에 있는데 페이크는 보통 아직 존재하지 않는 의존성을 대체하고자 구현한다
4.4 스텁으로 상호 작용 검증하지 말라
- 스텁과의 상호 작용을 검증하는 것은 취약한 테스트를 야기하는 안티 패턴이다
- 따라서 스텁은 SUT 내부로 들어오는 상호 작용을 모방하고 검사하지 않는다
- 검사를 하지 않는 이유는 SUT에서 스텁으로의 호출은 SUT가 생성하는 최종 결과가 아니기 때문이다
- 스텁과의 상호 작용을 검증하는 것은 더 이상 블랙박스 테스트가 아니다
- 스텁의 호출은 최종 결과를 산출하기 위한 수단일 뿐이다
- 따라서 스텁으로 상호 작용을 검증하면 SUT의 세부 구현 사항과 테스트와의 결합도가 올라가 리팩터링 내성이 없어진다
- 식별 가능한 동작의 최종 결과를 검증해야지 수단을 검증해서는 안된다
- 최종 결과가 아닌 사항을 검증하는 이러한 관행을 과잉 명세라고 부른다
5 식별할 수 있는 동작과 구현 세부 사항
- 스텁으로 상호작용을 검증하는 것은 구현 세부 사항을 검증하는 것이며 이는 테스트와의 강한 결합을 야기한다
- 이러한 강결합을 피하는 방법은 코드가 생성하는 최종 결과를 검증하고 구현 세부 사항과 테스트를 가능한 떨어뜨리는 것 뿐이다
- 그렇다면 구현 세부 사항은 정확히 무엇이며 식별할 수 있는 동작과 어떻게 다를까?
5.1 식별할 수 있는 동작과 공개 API는 다르다