一、使用JUnit + Mockito進(jìn)行單元測(cè)試
Java中的Mock工具有很多,比如Mockito, jMock, EasyMock等,在這里我們只說下Mockito,因?yàn)槠渌奈乙矝]用過:-D
下面省去怎么引入mockito的步驟,希望可以用不到1h的時(shí)間,讓大家可以使用Mockito寫出期望的單測(cè)。
二、實(shí)戰(zhàn)mockito
mockito是一款開源的測(cè)試框架,可以方便地通過mock(模擬)方式進(jìn)行測(cè)試驗(yàn)證??梢院芊奖愕馗鶭Unit結(jié)合起來用。為了更好地使用mockito,我們先來了解下mockito中的幾個(gè)核心概念。
2.1 mock
mock,就是偽造一個(gè)待測(cè)試的對(duì)象,可以隨意擺布,讓它干啥就干啥。
在mockito中,可以通過TestClass mockObject = mock(TestClass.class)來創(chuàng)建一個(gè)偽造的對(duì)象。
如果你調(diào)用mockObject中的方法,則什么事情都不會(huì)做,如果對(duì)應(yīng)方法有返回值的話,那就返回返回類型在JAVA中的默認(rèn)值。比如如果方法的返回值類型是boolean則返回false,如果返回值類型是String則返回null, List返回[]等
2.2 stub樁
樁(Stub),就是把要調(diào)用的方法模擬掉,讓方法按照我們的期望行動(dòng)。一般樁的目的,有三種
- doNothing : 啥也不做
- doReturn : 返回具體值
- doThrow: 拋出異常
對(duì)于doReturn,有兩種實(shí)現(xiàn)方法,
- when(mockObject.invokeMethod(...params)).thenReturn(...) : 會(huì)真正執(zhí)行invokeMethod內(nèi)的邏輯,只是返回值會(huì)為設(shè)定的返回值。
- doReturn(...).when(mockObject).invokeMethod(...params) : 不會(huì)真正執(zhí)行invokeMethod,只返回設(shè)定值。
doThrow邏輯跟doReturn一樣。
2.2 mock V.S. spy
我們?cè)谑褂胢ockito過程中,可以以mock的方式,也可以以spy的方式把實(shí)際的動(dòng)作給mock掉。如
TestClass object = mock(TestClass.class); // mock
TestClass object = spy(TestClass.class); // spy
這兩種方式有什么區(qū)別呢? 簡(jiǎn)而言之
mock就是對(duì)象是完完全全假的對(duì)象,其中所有的方法都會(huì)以樁的方式來執(zhí)行。
spy,又稱部分mock,如果設(shè)置了樁,則使用樁的返回值;如果未設(shè)置樁,則調(diào)用對(duì)象真實(shí)的方法
當(dāng)然你也可以指定mock對(duì)象具體方法的行為,在2.2節(jié)已經(jīng)講過。
2.3 使用mock class, 導(dǎo)致@Autowired的bean注入為Null
在spring的項(xiàng)目中,我們通常會(huì)在類中通過注解的方式注入對(duì)象,比如
public class PersonService {
@Autowired
private PersonDao personDao;
public String getPersonName(Long id) {
return personDao.getPersonName(id);
}
}
如果你在mockito的單測(cè)中,直接寫PersonService personService = mock(PersonService.class); 那在真正執(zhí)行g(shù)etPersonName(id)這個(gè)時(shí)候,對(duì)于personDao這個(gè)對(duì)象,是null。
原因就是單測(cè)對(duì)象被Mock掉之后,其中注入的對(duì)象spring是感知不到的。這個(gè)就跟我們自己通過new TestClass()方式無法注入@Autowired對(duì)象一個(gè)邏輯。
解決方案就是利用@InjectMocks 進(jìn)行注入,注意在單測(cè)跑之前需要調(diào)用MockitoAnnotations.initMocks(this);
具體可以參考: https://dzone.com/articles/use-mockito-mock-autowired
2.4 利用verify做驗(yàn)證
對(duì)于Mock的對(duì)象,由于我們就是為了把實(shí)際的操作給mock掉,那mockito怎么驗(yàn)證測(cè)試是否啟動(dòng)成功? 在mockito中,可以記錄每次調(diào)用的方法以及對(duì)應(yīng)的參數(shù),之后用verify進(jìn)行驗(yàn)證。
比如,verify(bar, times(1)).someMethod(); 來驗(yàn)證bar這個(gè)對(duì)象,調(diào)用了1次someMethod方法。