본문으로 건너뛰기

Mocking-Best-Practices

1 목 처리에 대한 모범 사례

  • 목은 테스트 대상 시스템과 의존성 간의 상호 작용을 모방하고 검사하는 데 도움이 되는 테스트 대역이다
  • 목은 비관리 의존성에만 적용해야한다
    • 다른 것에 목을 사용하면 깨지기 쉬운 테스트가 된다
    • 이 지침만 지키면 절반 이상의 성공을 거둔 것과 같다
    • 관리 의존성과 비관리 의존성은 Why-Integration-Testing.md 참고
  • 목에 대해 리팩터링 내성과 회귀 방지를 최대화해서 최대 가치의 통합 테스트를 개발하는데 도움이 되는 지침을 더 알아보자

관리 의존성

  • 전체를 제어할 수 있는 프로세스 외부 의존성을 관리 의존성이라 한다
  • 이러한 의존성은 애플리케이션을 통해서만 접근할 수 있다
    • 따라서 해당 의존성과의 상호 작용은 외부 환경에서 볼 수 없다
  • 좋은 예로 애플리케이션 데이터베이스가 있는데 이는 애플리케이션만 사용하는 데이터베이스르 말한다
    • 따라서 외부 시스템은 데이터베이스에 직접 접근하지 않고 애플리케이션에서 제공하는 API를 통해 접근한다
  • 관리 의존성과의 통신은 구현 세부사항이다
  • 관리 의존성은 통합 테스트에서 해당 의존성을 그대로 사용하라

비관리 의존성

  • 전체를 제어할 수 없는 프로세스 외부 의존성
  • 해당 의존성과의 상호 작용을 외부에서 볼 수 있다
  • 예를 들어 SMTP 서버와 메시지 버스 등이 있다
  • 비관리 의존성과의 통신은 시스템의 식별할 수 있는 동작이다
    • 해당 의존성은 목으로 대체해야 한다

2 목의 가치 극대화

2.1 시스템 끝에서 상호 작용 검증

2.2 목을 스파이로 대체

3 목 처리 모범 사례

3.1 목은 통합 테스트를 위한 것

  • 목은 통합 테스트만을 위한 것이며 단위 테스트에서 목을 사용하면 안된다
  • 코드는 두 가지 중 하나로 분류되며 둘 다는 아니다
    • 도메인 모델: 복잡한 처리
    • 컨트롤러: 프로세스 외부 의존성과 통신 처리
  • 도메인 모델에 대한 테스트는 단위 테스트 범주에 속한다
  • 컨트롤러를 다루는 테스트는 통합 테스트
  • 목은 비관리 의존성에만 적용이 가능하며 비관리 의존성은 처리하는 코드는 컨트롤러이기 때문에 컨트롤러를 테스트할 때만 목을 적용해야한다

3.2 테스트당 목의 개수

  • 테스트당 목은 하나 이상이 될 수 있다
  • 테스트의 단위는 코드 단위가 아니라 동작의 단위를 의미한다
  • 동작 단위를 구현하는데 단일 클래스부터 여러 클래스에 이르기까지 다양하게 걸쳐 있을 수 있다
  • 따라서 동작 단위를 검증하는데 필요한 목의 수는 관계가 없다
  • 목의 수는 운영에 참여하는 비관리 의존성 수에만 의존한다

3.3 호출 횟수 검증

  • 비관리 의존성과의 통신 검증은 아래 두 가지 모두를 확인해야 한다
    • 예상하는 호출이 있는가?
    • 예상치 못한 호출은 없는가?

3.4 보유 타입만 목으로 처리

  • 보유 타입만 목으로 처리하며 만약 서드파티 라이브러리를 사용할 경우 위에 어댑터를 작성하고 이 어댑터를 목으로 처리하라
  • 위 지침은 프로세스 내부 의존성에는 적용되지 않는다

서드파티 라이브러리 위에 어댑터를 만들고 목으로 대체하는 이유

  • 서트파티 코드의 작동 방식에 대해 깊이 이해하지 못하는 경우가 많다
  • 해당 코드가 이미 인터페이스를 제공하더라도 목으로 처리한 동작이 실제로 외부 라이브러리와 일치하는지 확인한다
    • 따라서 해당 인터페이스를 목으로 처리하는 것은 위험하다
  • 서드파티 코드의 기술 세부 사항까지는 꼭 필요하지 않다
  • 라이브러리를 업그레드할 때 서드파티 코드가 어떻게 변경될지 알 수 없으며 어댑터를 사용하지 않고 업그레이드를 하면 전체 코드베이스에 걸쳐 파급 효과가 일어날 수 있다

어탭터의 기능

  • 코드와 외부 환경 사이의 손상 방지 계층으로 작동한다
  • 라이브러리의 복잡성을 추상화한다
  • 라이브러리의 필요한 기능만 노출한다
  • 프로젝트 도메인 언어를 사용해 수행할 수 있다
  • 서드파티 코드 업그레이드 파급 효과를 어댑터 클래스 하나로 제한할 수 있다