前兩節介紹了什么是mock。
這節介紹如何使用mock。
對于從沒用過mock的讀者,請先安裝Mockito。它是一個優秀的mock框架。
使用mock的過程,就像裝一顆假牙。
讓我們跟著埃德蒙一起走進牙科醫院。
醫生診斷出埃德蒙的一顆牙已經壞了,需要用假牙替換掉它。
一星期后,假牙做好了,裝入埃德蒙的口中。做了幾次咬合動作,又被取出,打磨打磨。再裝進去。
直到醫生認為滿意為止。
整個配假牙的過程是:1 做假牙,2 配置假牙, 3 驗證功能。
讓我們跟著埃德蒙走出醫院,走進下面這個類:
public class NameChecker {
private NameLoader nameLoader;
private Alarmer alarmer;
public NameChecker(NameLoader loader_in, Alarmer alarmer_in) {
nameLoader = loader_in;
alarmer = alarmer_in;
}
public boolean nameIsOnServer(String addr, String name) {
List nameList = nameLoader.download(addr);
if (nameList.contains(name)) {
return true;
}
alarmer.reportAlarm("name is not in server.");
return false;
}
}
NameChecker類中有一個方法nameIsOnServer,用于檢查一個名字是不是記錄在服務器中。
nameIsOnServer有兩個參數,第一個參數是服務器地址,第二個參數是被檢查的名字。
如果name不在服務器中,則返回false,并且報警。
下面的這段ut,是對報警功能的驗證。
public class NameCheckerTest {
private NameChecker nameChecker;
private NameLoader nameLoader;
private Alarmer alarmer;
@Before
public void setUp() {
nameLoader = mock(NameLoader.class);
alarmer = mock(Alarmer.class);
nameChecker = new NameChecker(nameLoader, alarmer);
}
@Test
public void shouldReportAlarm(){
List<String> nameList = new ArrayList<String>();
nameList.add("a");
nameList.add("b");
when(nameLoader.download(anyString())).thenReturn(nameList);
String ladp_addr = "ldap://10.56.78.23:636";
String name = "c";
nameChecker.nameIsOnServer(ladp_addr, name);
verify(nameLoader, times(1)).download(anyString());
verify(alarmer, times(1)).reportAlarm(anyString());
}
}
NameLoader和Alarmer是與NameChecker合作的類。在ut中,一般需要使用假的合作類,以擺脫對它們的依賴,達到測試當前類的目標。
步驟1:調用Mockito的mock語句
nameLoader = mock(NameLoader.class);
alarmer = mock(Alarmer.class);
這就好比是做假牙。
假牙=mock(真牙)
步驟2:調用Mockito的when語句
when(nameLoader.download(anyString())).thenReturn(nameList);
這相當于打磨假牙,讓它用得舒服。
alarmer沒有相應的when語句,因為它簡單,無需打磨。
步驟3:調用Mockito的verify語句
verify(nameLoader, times(1)).download(anyString());
verify(alarmer, times(1)).reportAlarm(anyString());
這就是驗證牙齒的功能。
期望nameLoader的download方法被調用一次,alarmer的reportAlarm方法被調用一次。
實際被調用了嗎?
verify語句可以檢查出來。若符合期望,則ut狀態就是pass;不符合,則fail。