Mock 테스트와 Stub 테스트의 차이

1,241 단어·3 분·원문(.md)

사전 개념 #

Dummy #

Dummy 객체는 전달되지만 사용되지 않고 일반적으로 매개변수 목록을 채우는 목적으로만 사용됨

Fake #

Fake 객체는 실제로 작동하는 구현을 가지고 있지만 일반적으로 프로덕션에 적합하지 않는 몇가지 지름길을 사용

대표적 예시로는 메모리 데이터베이스가 있다.

Stub #

Stub은 테스트 중에 만들어진 호출에 미리 준비된 답변을 제공하며 일반적으로 테스트를 위해 프로그래밍된 것 외에는 전혀 응답하지 않는다.

Spy #

Spy는 어떻게 호출받았는지에 따라 일부 정보를 기록하는 Stub이다.

Mock #

Mock은 예상되는 기대값으로 미리 프로그래밍 객체이다.

테스트 대역(Test Double) #

위의 개념에 대해 이해하기전 우선 테스트 대역이라는 개념을 이해해야한다.

테스트 대역이란 테스트하려는 객체가 다른 객체들이 여러 관계가 엮여있어 사용하기 힘들 때, 대체할 수 있는 객체를 의미한다.

테스트 대역은 Dummey, Stub, Spy, Mock, Fake로 나누어진다.

Mock vs Stub #

일반적으로 많이 사용하는 두 개념에 대해서 정리를 하면 다음과 같다.

Test의 원칙에 따르면 하나의 테스트에는 여러 개의 스텁이 있을 수 있지만 일반적으로 모의는 하나만 있다.

Stub #

인스턴스화하여 구현한 가짜 객체(Dummy, 기능 구현 x)를 이용해 실제로 동작하는것 처럼 보이게 만드는 객체

해당 인터페이스나 클래스를 최소한으로 구현한다.

테스트에서 호출된 요청에 대해 미리 준비해둔 답변을 응답한다.

테스트시에 프로그래밍된 것 외에는 응답하지 않는다.

협력 객체의 특정 부분이 테스트가 어려운 경우, stub을 사용하여 수월하게 테스트할 수 있다.

Stub's Lifecycle #

  • Setup, 테스트 준비
  • Exercise, 테스트
  • Verify state, 상태 검증
  • Teardown, 리소스 정리

Mock #

호출에 대한 기대를 명세하고, 내용에 따라 동작하도록 프로그래밍된 객체

테스트 작성을 위한 환경 구축이 어려울 때, 테스트하고자 하는 코드와 엮인 객체들을 대신하여 만들어진 객체다.

행위 검증을 진행한다.

Mock's Lifecycle #

  • Setup data, 데이터 준비
  • Setup expectations, 예상되는 결과 준비
  • Exercise, 테스트
  • Verify expectations, 예상 검증
  • Verify state, 상태 검증
  • Teardown, 리소스 정리

Stub과 Mock의 차이 #

stub을 포함한 다른 대역들은 상태 검증(state verification)을 사용하고 Mock 오브젝트는 행위 검증(behavior verification)을 사용한다

상태 검증: 메서드가 수행된 후, 객체의 상태를 확인해 올바르게 동작했는지 확인하는 검증법
행위 검증: 메소드의 리턴 값으로 판단할 수 없는 경우, 특정 동작을 수행하는지 확인하는 검증법

검증의 대상이 다르다는 것이 중요한 체크요소다.

상태 검증 예시 #

StateClass stateClass = new StateClass();
stateClass.doSomething()

assertThat(stateClass.getStatus()).isEqualTo(true);

행위 검증 예시 #

BehaviorClass behaviorClass = new BehaviorClass();

verify(behaviorClass).doBehavior();

조금 더 상세한 예시 #

Stub #

사용하기 쉬우며 추가 종속성이 없다.

public class SimpleService implements Service {

    private Collaborator collaborator;

    public void setCollaborator(Collaborator collaborator){
        this.collaborator = collaborator;
    }

    // part of Service interface

    public boolean isActive(){
        return collaborator.isActive()
    }
}
public void testActiveWhenCollaboratorIsActive() throws Exception {

    service.setController(new Collaborator(){
        public boolean isActive(){
            return true;
        }
    });

    assertTrue(service.isActive());
}

Mock #

Collaborator collaborator = EasyMock.createMock(Collaborator.class);
EasyMock.expect(collaborator.isActive()).andReturn(true);
EasyMock.replay(collaborator);

service.setCollaborator(collaborator);
assertTrue(service.isActive());

EasyMock.verify(collaborator);

언제 Stub과 Mock을 사용하는가? #

기본적으로 적합하다고 판단될때(당연)

행위 검증(Mock)의 경우 특정 메서드의 호출 등을 검증하기 때문에 구현에 의존적이다.

상태 검증(Stub)의 경우 상태를 노출하는 메서드가 많이 추가될 수 있다.

많은 경우 상태 검증이 좋은 경우가 많다.

그러나 상태 검증이 어려운 경우가 있어서 이때는 행위 검증 혹은 전체 테스트를 진행하는 것도 좋은 방법이 된다.

Back-End/spring/mock_stub.md