一泰演、使用JUnit + Mockito進(jìn)行單元測試
Java中的Mock工具有很多,比如Mockito, jMock, EasyMock等,在這里我們只說下Mockito朝捆,因?yàn)槠渌奈乙矝]用過:-D
下面省去怎么引入mockito的步驟废亭,希望可以用不到1h的時間国章,讓大家可以使用Mockito寫出期望的單測。
二豆村、實(shí)戰(zhàn)mockito
mockito
是一款開源的測試框架液兽,可以方便地通過mock(模擬)方式進(jìn)行測試驗(yàn)證。可以很方便地跟JUnit結(jié)合起來用四啰。為了更好地使用mockito宁玫,我們先來了解下mockito中的幾個核心概念。
2.1 mock
mock柑晒,就是偽造一個待測試的對象欧瘪,可以隨意擺布,讓它干啥就干啥匙赞。
在mockito
中佛掖,可以通過TestClass mockObject = mock(TestClass.class)
來創(chuàng)建一個偽造的對象。
如果你調(diào)用mockObject中的方法涌庭,則什么事情都不會做芥被,如果對應(yīng)方法有返回值的話,那就返回返回類型在JAVA中的默認(rèn)值坐榆。比如如果方法的返回值類型是boolean則返回false拴魄,如果返回值類型是String則返回null, List返回[]等
2.2 stub樁
樁(Stub),就是把要調(diào)用的方法模擬掉猛拴,讓方法按照我們的期望行動羹铅。一般樁的目的,有三種
- doNothing : 啥也不做
- doReturn : 返回具體值
- doThrow: 拋出異常
對于doReturn愉昆,有兩種實(shí)現(xiàn)方法职员,
- when(mockObject.invokeMethod(...params)).thenReturn(...) : 會真正執(zhí)行invokeMethod內(nèi)的邏輯,只是返回值會為設(shè)定的返回值跛溉。
- doReturn(...).when(mockObject).invokeMethod(...params) : 不會真正執(zhí)行invokeMethod焊切,只返回設(shè)定值。
doThrow邏輯跟doReturn一樣芳室。
2.2 mock V.S. spy
我們在使用mockito過程中专肪,可以以mock的方式,也可以以spy的方式把實(shí)際的動作給mock掉堪侯。如
TestClass object = mock(TestClass.class); // mock
TestClass object = spy(TestClass.class); // spy
這兩種方式有什么區(qū)別呢? 簡而言之
mock就是對象是完完全全假的對象嚎尤,其中所有的方法都會以樁的方式來執(zhí)行。
spy伍宦,又稱部分mock芽死,如果設(shè)置了樁,則使用樁的返回值次洼;如果未設(shè)置樁关贵,則調(diào)用對象真實(shí)的方法
當(dāng)然你也可以指定mock對象具體方法的行為,在2.2節(jié)已經(jīng)講過卖毁。
2.3 使用mock class, 導(dǎo)致@Autowired的bean注入為Null
在spring的項(xiàng)目中揖曾,我們通常會在類中通過注解的方式注入對象,比如
public class PersonService {
@Autowired
private PersonDao personDao;
public String getPersonName(Long id) {
return personDao.getPersonName(id);
}
}
如果你在mockito的單測中,直接寫PersonService personService = mock(PersonService.class);
那在真正執(zhí)行g(shù)etPersonName(id)這個時候炭剪,對于personDao這個對象练链,是null。
原因就是單測對象被Mock掉之后念祭,其中注入的對象spring是感知不到的兑宇。這個就跟我們自己通過new TestClass()方式無法注入@Autowired對象一個邏輯。
解決方案就是利用@InjectMocks
進(jìn)行注入粱坤,注意在單測跑之前需要調(diào)用MockitoAnnotations.initMocks(this);
具體可以參考: https://dzone.com/articles/use-mockito-mock-autowired
2.4 利用verify做驗(yàn)證
對于Mock的對象隶糕,由于我們就是為了把實(shí)際的操作給mock掉,那mockito怎么驗(yàn)證測試是否啟動成功? 在mockito中站玄,可以記錄每次調(diào)用的方法以及對應(yīng)的參數(shù)枚驻,之后用verify進(jìn)行驗(yàn)證。
比如株旷,verify(bar, times(1)).someMethod();
來驗(yàn)證bar這個對象再登,調(diào)用了1次someMethod方法。