Open limjongheok opened 4 months ago
제가 찾아봤을 때는, 테스트 스텁과 Mock 중 어느 하나가 항상 더 좋다고 하기 보다는 테스트 상황에 따라 두 가지의 다른 접근 방식으로 사용을 해야 한다고 나왔습니다.
테스트 스텁은 일반적으로 정적이고 예측 가능한 결과를 반환하므로 단순한 시나리오에서에서 사용될 수 있다고 합니다. 예를 들면 항상 동일한 출력을 반환하는 함수의 단위 테스트에 적합하다고 합니다.
Mock은 호출된 메소드와 그에 대한 인자를 추적하고, 테스트 중에 동적으로 결과를 조작할 수 있기 때문에 다양한 결과를 얻거나 객체 간의 상호작용을 테스트 할 때 더 유용하다고 합니다. 예를 들면 객체 간의 통신이나 메소드 호출의 순서를 검증하고, 특정한 조건에서 다른 결과를 반환하는 동적인 상황에 적합하다고 합니다.
라고 위에 써놓긴 했는데, 설명이 너무 부실한 것 같아서 더 찾아보다가 좋은 예시가 있어서 찾아왔습니다.
위 블로그에서는 stub을 상태 검증, mock을 행위 검증이라고 설명하고 있습니다.
또 메일링 시스템을 예시로 두 테스트의 차이를 보여주고 있습니다. 해당 테스트는 어떠한 조건일 경우 고객에게 메일을 보내는 메일링 기능을 고객에게 실제로 메일 메세지를 보내지 않고 테스트하는 경우입니다.
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개인지 비교함으로써 올바른 상태값 이 나오는지 확인합니다.
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를 사용해서 메소드 호출 여부 등을 검증하고 있습니다.
mock Test 참고 기술 블로그입니다~ https://tech.kakaopay.com/post/mock-test-code/
책에서 테스트 스텁을 implements 를 받아 구현한 dummy 객체라 표현 하였습니다. 그렇다면 이렇게 만든 테스트 스텁은 항상 같은 결과만 기대할 수 있어 다양한 테스트를 하기 힘들거 같은데 그렇다면 테스트 스텁보다 다양한 결과를 얻을 수 있는 Mock 을 사용하는게 더 좋은 방식이라 볼 수 있을까요?? 만약 mock 이 아닌 테스트 스텁만을 사용할 테스트 환경은 무엇이 있을까요??