Mocking-Best-Practices
1 목 처리에 대한 모범 사례
- 목은 테스트 대상 시스템과 의존성 간의 상호 작용을 모방하고 검사하는 데 도움이 되는 테스트 대역이다
- 목은 비관리 의존성에만 적용해야한다
- 다른 것에 목을 사용하면 깨지기 쉬운 테스트가 된다
- 이 지침만 지키면 절반 이상의 성공을 거둔 것과 같다
- 관리 의존성과 비관리 의존성은 Why-Integration-Testing.md 참고
- 목에 대해 리팩터링 내성과 회귀 방지를 최대화해서 최대 가치의 통합 테스트를 개발하는데 도움이 되는 지침을 더 알아보자
관리 의존성
- 전체를 제어할 수 있는 프로세스 외부 의존성을 관리 의존성이라 한다
- 이러한 의존성은 애플리케이션을 통해서만 접근할 수 있다
- 따라서 해당 의존성과의 상호 작용은 외부 환경에서 볼 수 없다
- 좋은 예로 애플리케이션 데이터베이스가 있는데 이는 애플리케이션만 사용하는 데이터베이스르 말한다
- 따라서 외부 시스템은 데이터베이스에 직접 접근하지 않고 애플리케이션에서 제공하는 API를 통해 접근한다
- 관리 의존성과의 통신은 구현 세부사항이다
- 관리 의존성은 통합 테스트에서 해당 의존성을 그대로 사용하라
비관리 의존성
- 전체를 제어할 수 없는 프로세스 외부 의존성
- 해당 의존성과의 상호 작용을 외부에서 볼 수 있다
- 예를 들어 SMTP 서버와 메시지 버스 등이 있다
- 비관리 의존성과의 통신은 시스템의 식별할 수 있는 동작이다
- 해당 의존성은 목으로 대체해야 한다
2 목의 가치 극대화
2.1 시스템 끝에서 상호 작용 검증
2.2 목을 스파이로 대체
3 목 처리 모범 사례
3.1 목은 통합 테스트를 위한 것
- 목은 통합 테스트만을 위한 것이며 단위 테스트에서 목을 사용하면 안된다
- 코드는 두 가지 중 하나로 분류되며 둘 다는 아니다
- 도메인 모델: 복잡한 처리
- 컨트롤러: 프로세스 외부 의존성과 통신 처리
- 도메인 모델에 대한 테스트는 단위 테스트 범주에 속한다
- 컨트롤러를 다루는 테스트는 통합 테스트다
- 목은 비관리 의존성에만 적용이 가능하며 비관리 의존성은 처리하는 코드는 컨트롤러이기 때문에 컨트롤러를 테스트할 때만 목을 적용해야한다
3.2 테스트당 목의 개수
- 테스트당 목은 하나 이상이 될 수 있다
- 테스트의 단위는 코드 단위가 아니라 동작의 단위를 의미한다
- 동작 단위를 구현하는데 단일 클래스부터 여러 클래스에 이르기까지 다양하게 걸쳐 있을 수 있다
- 따라서 동작 단위를 검증하는데 필요한 목의 수는 관계가 없다
- 목의 수는 운영에 참여하는 비관리 의존성 수에만 의존한다
3.3 호출 횟수 검증
- 비관리 의존성과의 통신 검증은 아래 두 가지 모두를 확인해야 한다
- 예상하는 호출이 있는가?
- 예상치 못한 호출은 없는가?
3.4 보유 타입만 목으로 처리
- 보유 타입만 목으로 처리하며 만약 서드파티 라이브러리를 사용할 경우 위에 어댑터를 작성하고 이 어댑터를 목으로 처리하라
- 위 지침은 프로세스 내부 의존성에는 적용되지 않는다
서드파티 라이브러리 위에 어댑터를 만들고 목으로 대체하는 이유
- 서트파티 코드의 작동 방식에 대해 깊이 이해하지 못하는 경우가 많다
- 해당 코드가 이미 인터페이스를 제공하더라도 목으로 처리한 동작이 실제로 외부 라이브러리와 일치하는지 확인한다
- 따라서 해당 인터페이스를 목으로 처리하는 것은 위험하다
- 서드파티 코드의 기술 세부 사항까지는 꼭 필요하지 않다
- 라이브러리를 업그레드할 때 서드파티 코드가 어떻게 변경될지 알 수 없으며 어댑터를 사용하지 않고 업그레이드를 하면 전체 코드베이스에 걸쳐 파급 효과가 일어날 수 있다
어탭터의 기능
- 코드와 외부 환경 사이의 손상 방지 계층으로 작동한다
- 라이브러리의 복잡성을 추상화한다
- 라이브러리의 필요한 기능만 노출한다
- 프로젝트 도메인 언어를 사용해 수행할 수 있다
- 서드파티 코드 업그레이드 파급 효과를 어댑터 클래스 하나로 제한할 수 있다