2016년 4월 26일 화요일

Mocks Aren't Stubs



마틴 파울러의 Mocks Aren't Stubs라는 글 소개. 이전에 사내에서 메일로 보냈던 글
-----------------------------------

Mocks aren't stubs 라는 제목의 마틴 파울러의 에세이를 요약해보았습니다.
http://martinfowler.com/articles/mocksArentStubs.html

마틴 파울러는 이 에세이에서 테스트 목적으로 진짜 객체 대신에 사용하는 객체들을 부르는 이름으로 Gerard Meszaros 가 사용한 용어를 따라 "테스트 더블"을 사용합니다. "스턴트 더블"을 응용한 이름입니다.

테스트 더블의 대표적인 사례로 다음을 들고 있고 각각을 다음과 같이 설명합니니다.


  • dummy - 전달은 되지만 실제로는 사용되지 않는 객체. 보통은 함수 파라메터를 채우는 때 사용됩니다.
  • fake - 실제로 동작하는 구현을 포함하고 있지만 지름길들을 이용하고 있고 상업적 용도로 사용할만한 구현은 아닌 것. 메모리 DB를 예로 들고 있습니다.
  • stub - 테스트 도중에 예상되는 값을 반환할 수 있도록 만들어져서 다른 결과값은 주지 못하는 객체입니다.
  • mock - 이 에세이에서 중점적으로 설명하고 있는 대상입니다. "제목은 mock은 stub이 아니다" 이지만 실제로는 mock과 mock이 아닌 것으로 나눠서 설명하는 형태에 가깝습니다.


다른 세 가지의 test double과 비교해서 mock은 확연하게 구분되는 특성이 있는데, 그것은 state를 예측할뿐만 아니라 behavior도 예측한다는 것입니다. 테스트 도중에 email을 보내는 내용을 포함하는 클래스를 test double로 대체한 다음의 코드에서 이것을 볼 수 있습니다.

아래는 stub을 이용할 때의 테스트 코드입니다. 주문을 받고 창고에 재고를 확인하고, 부족한 경우에 이메일을 발송하는 과정을 테스트하는 코드입니다. 자바로 작성되어 있습니다.


class OrderStateTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    MailServiceStub mailer = new MailServiceStub();
    order.setMailer(mailer);
    order.fill(warehouse);
    assertEquals(1, mailer.numberSent());
  }

...

}
MailService 클래스의 numberSent를 호출해서. 내부의 값, state를 확인합니다. 반면에 mock을 이용하는 테스트는 다음과 같습니다.

class OrderInteractionTester...
  public void testOrderSendsMailIfUnfilled() {
    Order order = new Order(TALISKER, 51);
    Mock warehouse = mock(Warehouse.class);
    Mock mailer = mock(MailService.class);
    order.setMailer((MailService) mailer.proxy());

    mailer.expects(once()).method("send");
    warehouse.expects(once()).method("hasInventory")
      .withAnyArguments()
      .will(returnValue(false));

    order.fill((Warehouse) warehouse.proxy());
  }

...

}
Mock을 이용할 때는 mailer.expects(once()).method("send") 라는 코드를 통하여, 상태값이 아니라 send라는 메소드가 호출되는 동작을 예상하고 이것의 일치 여부를 확인하는 것을 볼 수 있습니다. 이렇게 state의 값이 아니라 behavior를 예상하는 mock 객체의 활용은 BDD(Behavior Driven Development)로 이어집니다. 더 자세한 내용을 알고 싶으시면 서두에 첨부한 마틴 파울러의 에세이를 직접 읽어보시면 좋을 것으로 생각됩니다. 감사합니다.

댓글 없음:

댓글 쓰기