Stub과 단위 테스트 (Mockito or 직접 구현)

단위 테스트(Unit Test)는 ①각각 독립된 하나의 기능을 테스트하면서 ②언제나 같은 결과를 기대할 수 있어야 하고, ③빠르게 결과(성공/실패)를 확인할 수 있어야 하며, ④테스트 스위트 실행 후 결과를 취합할 수 있도록 작성되어야 합니다.

단위 테스트를 작성하다 보면 ②를 만족시키기 위해서 특정 메서드를 stub으로 만들어야 할 때가 있습니다. 예를 들면, 외부 시스템과의 통신이나 Date, System 등 유틸리티 클래스의 메서드가 있습니다. Date.Now(), 외부 시스템과의 통신 같은 경우는 코드를 그대로 사용하면 반환 값이 고정되어 있지 않아서 언제나 같은 결과를 기대할 수 없습니다. System.exit() 같은 경우는 실행되었을 때 테스트가 종료되어 결과(성공/실패)를 알 수 없게 됩니다. 또한, 인터페이스는 정의되어 있지만 구현체가 아직 구현되지 않은 경우도 있을 수 있습니다. 우리는 이런 상황들에서 단위 테스트를 작성하기 위해 스텁을 고려하게 됩니다.

Stub이란?

요청에 대한 응답을 단순하게 미리 정의해둔 것을 스텁이라고 합니다. 단위 테스트를 위해 반환 값이 있는 메서드를 stub으로 만들게 됩니다.

Stub 만드는 방법

stub을 만드는 방법은 크게 두 가지가 있습니다.
첫 번째는 Mockito, Jmockit과 같은 라이브러리를 사용하는 방법, 두 번째는 직접 Interface와 구현체를 만드는 방법입니다.

이해를 돕기 위해 RandomPrefixAdder라는 클래스가 있다고 생각해 봅시다. RandomPrefixAdder는 문자열에 파라미터로 전달 받은 길이의 랜덤 prefix를 붙여주는 메서드를 가지고 있습니다. 상상력을 더해서 해당 클래스는 prefix를 얻기 위해 외부 시스템과 통신한다고 가정해 봅시다.

stub을 만드는 방법
Mockito 사용하기 OR Interface와 구현체 구현하기

Mockito 라이브러리 사용

Mockito는 특정 클래스를 손쉽게 mock 객체로 만들어 주고, mock 객체에 stub 메서드를 정의하거나, stub된 메서드의 실행 횟수 등을 검증할 수 있게 도와줍니다. 참고로 static method는 JMockit을 사용하면 스텁으로 만들 수 있습니다.

Mockito 사용 예시

@Test
void createPowerString() {
  String input = "InputValue";
  PowerPrefixAdder mockPpa = Mockito.mock(PowerPrefixAdder.class);
  Mockito.when(mockPpa.powerString(input, 5)).thenReturn("PowerInputValue");

  String result = mockPpa.powerString(input, 5);

  Assertions.assertThat(result).isEqualTo("PowerInputValue");
}

직접 구현하기

직접 인터페이스를 만들어 객체를 추상화 하면 단위 테스트를 작성할 때 특정 객체를 직접 개발한 가짜 객체로 바꿀 수 있도록 작성할 수 있습니다. 가짜 객체가 스텁 역할을 하도록 간단하게 구현해 두면 항상 같은 결과를 기대할 수 있게 됩니다.

직접 구현 예시

interface PowerPrefixAdder {
  public String powerString(String input, int length);
}

class DefaultPowerPrefixAdder implements PowerPrefixAdder {
  public String powerString(String input, int length) {
    if (length == 5) {
      return "Power" + input;
    }
    return "";
  }
}

@Test
void createPowerString() {
  String input = "inputValue";
  PowerPrefixAdder mockPpa = new DefaultPowerPrefixAdder();

  String result = mockPpa(input, 5);

  Assertions.assertThat(result).isEqualTo("PowerInputValue");
}
스스로 경험하며 얻은 깨달음을 공유하기 좋아하며, 세상이 필요로 하는 코드를 작성하기 위해 노력하는 개발자입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다