[자바/스프링, 테스트] 목 객체와 Mockito를 사용한 테스트

목 객체

목(mock) 객체란 테스트 대상 객체가 다른 객체(의존 객체)에 의존하고 있는 경우 의존 객체 대신 기능을 수행하는 가짜(double) 객체를 말한다.

외부 서비스(예: 데이터베이스, API 등)와 연결된 애플리케이션의 동작을 테스트하기 위해서는 해당 서비스가 모두 준비되어 있어야 한다. 테스트를 위한 외부 서비스 구성이 모두 준비되어 있다면 완전한 테스트가 가능하겠지만 그렇지 않은 경우 해당 서비스들과 관련된 의존 객체들을 대신하여 동작할 수 있는 목 객체를 사용하면 테스트를 보다 용이하게 할 수 있다.

미리 준비된 데이터(하드코딩된 데이터)를 제공하도록 정의된 의존 객체를 대상으로 테스트를 수행하는 스텁(stub) 객체와 달리, 목 객체를 이용한 테스트에서는 의존 객체를 대체하는 목 객체가 어떻게 동작할 것이라고 설정한 후 해당 의존 객체의 기능을 실행하고 그 결과를 확인함으로써 테스트를 수행한다. 목 객체에게 어떤 메서드를 어떻게 호출해야 할지 지시하고 어떤 일이 일어났는지 확인하는 것이다. 이를 목 객체의 녹음(record) 및 재생(playback) 메커니즘이라고 한다. 스텁 객체가 데이터에 초점이 맞추어져 있다면 목 객체는 동작 및 행위에 초점이 맞추어져 있다.

목 객체를 사용한 테스트는 다음 과정으로 이루어진다.

  1. 테스트 대상 객체 선정 및 목 객체 생성: 객체에 의존성 주입되어 있는 의존 객체를 테스트 대상 객체로 정한 후 목 객체로 생성한다.
  2. 설정 (녹음): 목 객체의 특정 메서드가 어떤 일을 수행하는지 설정한다.
  3. 실행 (재생): 설정한 목 객체의 테스트 대상 메서드가 실행되는 코드를 실행한다.
  4. 확인 (단정): 목 객체의 특정 메서드가 실제로 호출되었는지 확인한다.

목 객체를 통해 데이터베이스를 사용하는 서비스의 동작을 테스트하는 과정은 다음과 같다.

  1. 테스트 대상 객체 선정 및 목 객체 생성: 서비스 인터페이스 구현체에 의존성 주입되어 있는 리포지토리 인터페이스 구현체를 테스트 대상 객체의 의존 객체로 정한 후 목 객체로 생성한다.
  2. 설정 (녹음): 리포지토리 구현체 목 객체의 특정 메서드가 어떤 일을 수행하는지 설정한다.
  3. 실행 (재생): 설정한 리포지토리 구현체 목 객체의 테스트 대상 메서드가 실행되는 코드를 실행한다.
  4. 확인 (단정): 리포지토리 구현체 목 객체의 특정 메서드가 실제로 호출되었는지 확인한다.


Mockito 라이브러리

Mockito 라이브러리를 사용하여 인터페이스 또는 클래스를 대상으로 목 객체를 동적으로 쉽게 생성할 수 있다. 생성된 목 객체를 대상으로 테스트 대상 메서드의 실행 방식을 지정한 후 실행 테스트를 수행하면 된다. 메서드의 호출 횟수, 메서드 호출 시 전달된 인자의 종류 및 개수 등의 확인도 가능하다.

Mockito 라이브러리를 통해 생성한 목 객체를 사용하는 방법은 다음과 같다.

  1. 설정 (녹음): Mockito.when() 메서드를 사용하여 목 객체의 특정 메서드가 어떤 일을 수행하는지 설정한다.
  2. 실행 (재생): 목 객체의 테스트 대상 메서드가 실행되는 코드를 실행한다.
  3. 확인 (단정): Mockito.then() 메서드를 사용하여 목 객체의 특정 메서드가 실제로 수행되었는지 확인한다.


코드 예제

@SpringBootTest
public class MockitoTest {
    @Mock
    private MyRepository myRepository;
  
    @InjectMock
    private MyService myService;
  
    @Test
    public void repositoryMockTest() {
        Mockito.when(myRepository.getData()).thenResult(리포지토리_구현체_메서드의_예상_반환_결과);
        Assert.assertEquals(myService.getData(), 서비스_구현체_메서드의_예상_반환_결과);
    }
}


참고

Comments