SSAFY11th-book-study / book-study

0 stars 0 forks source link

[5.4.3] 테스트 스텁 #50

Open limjongheok opened 4 months ago

limjongheok commented 4 months ago

책에서 테스트 스텁을 implements 를 받아 구현한 dummy 객체라 표현 하였습니다. 그렇다면 이렇게 만든 테스트 스텁은 항상 같은 결과만 기대할 수 있어 다양한 테스트를 하기 힘들거 같은데 그렇다면 테스트 스텁보다 다양한 결과를 얻을 수 있는 Mock 을 사용하는게 더 좋은 방식이라 볼 수 있을까요?? 만약 mock 이 아닌 테스트 스텁만을 사용할 테스트 환경은 무엇이 있을까요??

sootudio commented 4 months ago

제가 찾아봤을 때는, 테스트 스텁과 Mock 중 어느 하나가 항상 더 좋다고 하기 보다는 테스트 상황에 따라 두 가지의 다른 접근 방식으로 사용을 해야 한다고 나왔습니다.

테스트 스텁은 일반적으로 정적이고 예측 가능한 결과를 반환하므로 단순한 시나리오에서에서 사용될 수 있다고 합니다. 예를 들면 항상 동일한 출력을 반환하는 함수의 단위 테스트에 적합하다고 합니다.

Mock은 호출된 메소드와 그에 대한 인자를 추적하고, 테스트 중에 동적으로 결과를 조작할 수 있기 때문에 다양한 결과를 얻거나 객체 간의 상호작용을 테스트 할 때 더 유용하다고 합니다. 예를 들면 객체 간의 통신이나 메소드 호출의 순서를 검증하고, 특정한 조건에서 다른 결과를 반환하는 동적인 상황에 적합하다고 합니다.

sootudio commented 4 months ago

라고 위에 써놓긴 했는데, 설명이 너무 부실한 것 같아서 더 찾아보다가 좋은 예시가 있어서 찾아왔습니다.

https://ssyoni.tistory.com/31

위 블로그에서는 stub을 상태 검증, mock을 행위 검증이라고 설명하고 있습니다.

또 메일링 시스템을 예시로 두 테스트의 차이를 보여주고 있습니다. 해당 테스트는 어떠한 조건일 경우 고객에게 메일을 보내는 메일링 기능을 고객에게 실제로 메일 메세지를 보내지 않고 테스트하는 경우입니다.

stub을 사용한 테스트

public interface MailService {
  public void send (Message msg);
}
public class MailServiceStub implements MailService {
  private List<Message> messages = new ArrayList<Message>();
  public void send (Message msg) {
    messages.add(msg);
  }
  public int numberSent() {
    return messages.size();
  }
}
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());
  }

해당 테스트에서는 보낸 메일의 개수가 1개인지 비교함으로써 올바른 상태값 이 나오는지 확인합니다.

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 object를 사용해서 메소드 호출 여부 등을 검증하고 있습니다.

hj-k66 commented 4 months ago

mock Test 참고 기술 블로그입니다~ https://tech.kakaopay.com/post/mock-test-code/