Mock和Stub的比較
Martin Fowler 寫過一篇文章, 叫"Mocks aren’t stubs" (http://martinfowler.com/articles/mocksArentStubs.html). 討論Mock和 stub的不同
說真的一開始看了半天, 不是很懂他要講什麼, 後來在網路上看了半天, 終於比較有感覺了. 以下是我簡單的整理.
首先我們首先看個例子:
(1)定義一個 Mail Service的interface
public interface MailService {
public void send (Message msg);
}
(2) 實做一個Mail Service的stub
public class MailServiceStub implements MailService {
private List
public void send (Message msg) {
messages.add(msg);
}
public int numberSent() {
return messages.size();
}
}
(3) 寫一個測試程式, 是利用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());
}
這是大多數人的作法. 先準備一下資料, 餵給受測程式, 然後檢查傳回值是否正確, 或者看看傳給stub的東西對不對.
(4) 寫一個測試程式, 是利用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和stub有點不一樣, 先準備好一些預期的值傳回給受測程式, 然後再呼叫受測程式. 所以它的重點不是在準備資料給受測程式, 而是在確認受測程式和被受測程式呼叫者之間的interaction是否正確.
因此可以簡單說mock和stub之間的差異是:
Stub
- Provide canned answers to call made during the test
- Stubs provide input for the application under test so that the test can be performed on something else.
- Validate a return value from a method call
Mock
- objects pre-programmed with expectations which form a specification of the calls they are expected to receive
- Mocks provide input to the test to decide on pass\fail.
- Verify the expected interaction between a class and its dependencies.