Test Doubles

테스트 대역(Test Doubles)이란?

테스트 대역이란 쉽게 얘기하면 실제 객체를 대신해서 테스팅에 사용하는 모든 방법을 일컫는 호칭이다.

실제 객체는 사용하기 어렵고.. 대신 이를 수행할 수 있는 객체를 만들어 테스트를 수행하도록 돕는것이다.

다른말로 표현하면,

  • 테스트할 때 실제 객체 대신 사용되는 모든 종류의 가짜 객체를 의미

  • 실제 객체를 사용하기 어렵거나 비효율적인 경우 대체하여 사용

  • 테스트하려는 객체가 다른 객체들과 복잡한 관계가 엮여있어 사용하기 힘든 경우, 대체할 수 있는 객체

테스트 대역은 Dummy, Stub, Spy, Mock, Fake 등이 존재한다.

1. 더미 객체(Dummy Objects)

가장 단순한 형태의 대역이다. 단순히 파라미터를 채우기 위해 사용 사용하고, 실제로는 사용되지 않으며 객체의 메소드가 호출되지 않는다.

  • 함수 파라미터에 전달되는 빈 객체 등

public class DummyCustomer implements Customer {
    public String getName() {
        return null;  // 사용되지 않으므로 의미 없는 값 반환
    }
}

필수 파라미터이지만 테스트에서 실제로 사용되지 않는 객체를 전달할 때 사용한다.

2. 스텁(Stub)

스텁은 미리 준비된 결과를 반환하는 객체이다. 테스트 중 호출될 때 미리 정해진 값을 반환한다. 테스트를 위해서 프로그래밍된 것 외에는 응답하지 않는다.

  • 조건부 로직이나 여러 상황에 따른 응답은 구현하지 않는다.

주로 외부 의존성(DB, 외부 API 등)을 대체할 때 사용한다. 예시로는 DB 조회 결과를 미리 정의하는 경우이다.

3. 스파이(Spy)

메서드 호출 횟수, 전달된 파라미터 등과 같은 전반적인 호출을 기록한다.

  • 스텁의 기능 + 호출 내역 기록

  • 실제 객체를 부분적으로 감싸서 사용할 수도 있음

4. 페이크(Fake)

실제 (작동하는)구현과 유사하지만 단순화된 구현을 제공한다. 실제 DB 대신 메모리 DB를 사용하는 것이 대표적이다.

Fake를 사용하는 주요 상황은 아래와 같다.

  1. 인메모리 DB가 필요한 경우

  2. 복잡한 비즈니스를 단순화할 때

    • 실제 결제 시스템 대신 항상 성공하는 Fake 결제 시스템

    • 실제 이메일 발송 대신 로그만 남기는 Fake 이메일 서비스

  3. 외부 서비스와의 통합 테스트

    • 실제 외부 API 대신 미리 정의된 응답을 주는 Fake 서버

Stub은 미리 정의된 응답만 반환하지만 Fake는 실제로 동작하는 구현을 가진다는 점에서 차이가 있다.

또, 인메모리 DB를 대체하기 때문에 상태를 가질 수 있다.

  • Fake 객체가 내부적으로 데이터를 저장하고 관리할 수 있다는 의미

5. 모의 객체(Mock)

가장 복잡하고 강력한 테스트 더블이다. 예상되는 호출과 그에 대한 응답에 대해서 프로그래밍이 가능하다. 그래서 예상된 대로 사용하거나 동작하는지 검증한다.

  • 행위 검증(behavior verification)에 집중하고 테스트 대상 코드가 Mock과 어떻게 상호작용하는지를 검증한다.

Mock을 사용하는 주요 상황은 아래와 같다.

  1. 외부 시스템과의 통합 테스트

    • 외부 API 호출

    • DB 연동

    • 메시징 시스템

  2. 의존성이 많은 서비스 계층 테스트

    • 여러 레포지트로를 사용하는 서비스 객체

    • 외부 서비스를 호출하는 로직

  3. 예외 상황 테스트

    • 네트워크 오류, 타임아웃, 데이터 유효성 검증

과도한 Mock 사용은 테스트 유지보수를 어렵게 만들고 실제 동작과 차이가 발생할 수 있어서 조심해야 한다.

또한, 단순히 결과값만 검증하는 것이 아니라 행위 검증에 집중해야 한다.

Last updated