Mock, Stub, 그리고 Spy 객체

양성준·2025년 5월 18일

스프링

목록 보기
38/49

Mock

정의

  • 실제 객체를 대체하는 ‘가짜 객체’로, 내부 동작이 구현되어 있지 않고 원하는 동작을 명시적으로 지정해야 한다.
    • 테스트를 위해 만든 "가짜 객체" 그 자체, 동작을 지정하면 Stub
  • 메서드의 반환값, 예외 발생 등을 사전에 설정할 수 있으며, 메서드 호출 여부(verify)도 검증할 수 있다.

특징

  • 실제 로직은 실행되지 않음
  • 모든 동작은 명시적으로 지정해야 함 -> Stub
  • 테스트 대상과의 상호작용(호출 여부, 호출 횟수 등) 검증에 적합

예시

List<String> mockList = Mockito.mock(List.class);
Mockito.when(mockList.size()).thenReturn(5);

assertEquals(5, mockList.size()); // 5 반환
Mockito.verify(mockList).size();  // 호출 여부 검증

적합한 상황

  • 외부 시스템, 복잡한 의존성 등 실제 객체를 사용하기 어려울 때
  • 호출 여부, 횟수, 파라미터 등 상호작용 자체를 검증할 때
  • 테스트 격리와 속도가 중요한 경우

Stub

정의

  • Mockito에서는 보통 Mock 객체에 대해 when(...).thenReturn(...) 또는 doReturn(...).when(...)을 사용해 Stub을 만든다.

특징

  • Mock(혹은 Fake) 객체에 "특정 메서드가 호출되면 정해진 값을 반환"하도록 미리 행동을 지정한 것
  • 실제 객체의 동작을 단순화하여 테스트 대상의 환경을 제어
  • 복잡한 로직 없이, 입력에 대해 미리 정해진 결과만 반환

예시

List<String> mockList = Mockito.mock(List.class);
Mockito.when(mockList.size()).thenReturn(10); // Stub 설정

assertEquals(10, mockList.size()); // 항상 10 반환

적합한 상황

  • 테스트 대상이 의존하는 객체의 특정 동작만 제어하고 싶을 때
  • 외부 시스템의 상태나 결과를 시뮬레이션할 때
  • 예외 상황, 경계값 등 다양한 시나리오를 쉽게 구현하고 싶을 때

Spy

정의

  • 실제 객체를 감싸서 만들어진 부분 Mock 객체
  • 실제 객체의 동작을 대부분 유지하면서, 특정 메서드만 Stub하거나 호출 여부를 감시할 수 있다.

특징

  • 실제 객체의 메서드가 기본적으로 실행됨
  • 필요한 메서드만 Stub 가능
  • 호출 기록(verify)도 가능

예시

public class SimpleService {
    private final List<String> store = new ArrayList<>();

    public void add(String value) {
        store.add(value);
    }

    public int count() {
        return store.size();
    }

    public String get(int index) {
        return store.get(index);
    }
}


public class SimpleServiceTest {
    @Test
    void spyExample() {
        // 실제 객체 생성
        SimpleService realService = new SimpleService();

        // Spy로 감싼다
        SimpleService spyService = spy(realService);

        // 실제 동작: add, get은 원래대로 동작
        spyService.add("A");
        spyService.add("B");
        assertEquals("A", spyService.get(0));

        // 특정 메서드만 Stub(가짜 동작 부여)
        doReturn(100).when(spyService).count();

        // count()만 가짜 값, 나머지는 실제 동작
        assertEquals(100, spyService.count());
        assertEquals("B", spyService.get(1));

        // 실제 메서드 호출 여부 검증도 가능
        verify(spyService, times(2)).add(anyString());
    }
}

적합한 상황

  • 실제 객체의 동작 대부분은 그대로 두고, 일부만 제어하거나 감시하고 싶을 때
  • 상태 변화가 중요한 객체의 일부 동작만 가짜로 만들고 싶을 때
  • 복잡한 객체에서 전체 Mock이 오히려 번거로울 때

선택 기준 및 실무 예시

  • 실무에서는 Mock과 Stub을 혼용하며, 실제 객체의 일부만 제어가 필요하면 Spy를 사용
profile
백엔드 개발자

0개의 댓글