1.JUnit:能夠直接在PC上執(zhí)行罕邀;AndroidTest:需要依賴Android設(shè)備;
2.測試有返回值得方法用Junit,void方法用Mock。
Mock概念:所謂的mock就是創(chuàng)建一個類的虛假的對象啊央,在測試環(huán)境中眶诈,用來替換掉真實的對象,以達到兩大目的:
1)驗證這個對象的某些方法的調(diào)用情況瓜饥,調(diào)用了多少次逝撬,參數(shù)是什么等等
2)指定這個對象的某些方法的行為,返回特定的值乓土,或者是執(zhí)行特定的動作
3.驗證方法是否調(diào)用宪潮,且參數(shù)是否正確
Mockito.verify(objectToVerify).methodToVerify(arguments);
其中,objectToVerify和methodToVerify分別是你想要驗證的對象和方法趣苏。對應(yīng)上面的例子
4.Mockito.mock()與Mockito.spy()兩個方法的區(qū)別:
mock()方法對象的所有非void方法都將返回默認值:int狡相,long類型返回0,boolean方法返回false食磕,對象方法返回null等等谣光,而void方法將什么都不做。
spy()方法對象既能驗證方法調(diào)用的功能芬为,同時又能調(diào)用這個方法的默認實現(xiàn)(mock對象調(diào)用默認實現(xiàn)都將返回默認值)
針對這mock()與spy()有返回值得情況舉個例子:
//假設(shè)目標類的實現(xiàn)是這樣的
public class PasswordValidator {
public boolean verifyPassword(String password) {
return "xiaochuang_is_handsome".equals(password);
}
}
測試代碼如下:
@Test
public void testSpy() {
//跟創(chuàng)建mock類似,只不過調(diào)用的是spy方法蟀悦,而不是mock方法媚朦。spy的用法
PasswordValidator spyValidator = Mockito.spy(PasswordValidator.class);
//PasswordValidator spyValidator = Mockito.mock(PasswordValidator.class);這種情況無論傳何值都將返回false
//在默認情況下,spy對象會調(diào)用這個類的真實邏輯日戈,并返回相應(yīng)的返回值询张,這可以對照上面的真實邏輯
spyValidator.verifyPassword("xiaochuang_is_handsome"); //true
spyValidator.verifyPassword("xiaochuang_is_not_handsome"); //false
//spy對象的方法也可以指定特定的行為
Mockito.when(spyValidator.verifyPassword(anyString())).thenReturn(true);
//同樣的,可以驗證spy對象的方法調(diào)用情況
spyValidator.verifyPassword("xiaochuang_is_handsome");
Mockito.verify(spyValidator).verifyPassword("xiaochuang_is_handsome"); //pass
}
“void方法什么都不做”我的理解是當(dāng)mock的對象中的void方法中調(diào)用了另一個mock對象的方法時浙炼,另一個mock對象的方法不會執(zhí)行
針對mock()與spy()無返回值的情況舉個例子:LoginActivity中有個login方法如下:
public void login(View view) {
String userName = mUserName.getText().toString();
String password = mPassword.getText().toString();
mLoginPresenter.loginPresent(userName, password);
}
可以看到LoginActivity中的login()方法調(diào)用了LoginPresenter中的loginPresent()方法份氧,而LoginPresenter中的loginPresent方法代碼如下:
public class LoginPresenter {
private UserManager mUserManager;
public void loginPresent(String username, String password) {
mUserManager.performLogin(username, password);
}
public void setUserManager(UserManager userManager) { //<==
this.mUserManager = userManager;
}
}
可以看到LoginPresenter中的loginPresent()方法又調(diào)用了UserManager的performLogin()方法,現(xiàn)在我們看下測試代碼弯屈,如下:
@Test
public void login() throws Exception {
LoginActivity loginActivity = Robolectric.setupActivity(LoginActivity.class);
loginActivity.mLoginPresenter = Mockito.spy(LoginPresenter.class);//正確
//loginActivity.mLoginPresenter = Mockito.mock(LoginPresenter.class);//錯誤
UserManager userManager = Mockito.mock(UserManager.class);
loginActivity.mLoginPresenter.setUserManager(userManager);
((EditText)loginActivity.findViewById(R.id.et_username)).setText("xiaochuang");
((EditText)loginActivity.findViewById(R.id.et_password)).setText("xiaochuang is handsome");
loginActivity.mLoginBtn.performClick();
//verify(loginActivity.mLoginPresenter).login("xiaochuang", "xiaochuang is handsome"); //mock or spy all success;
verify(userManager).performLogin("xiaochuang", "xiaochuang is handsome");//mock error ; spy success
}
如上代碼可以看出蜗帜,當(dāng)LoginPresenter對象是通過mock()方法獲取的話,運行失敗资厉,我的理解是mock()方法獲取的mLoginPresenter在調(diào)用loginPresent()方法時返回了個什么都沒做厅缺,導(dǎo)致 mUserManager.performLogin(username, password);都沒有執(zhí)行 所以報Actually, there were zero interactions with this mock.