欧美企业必备技能-Mockito
歐美企業(yè)做開發(fā)除了英語(yǔ)是必備技能之外,使用Mockito寫unit test(單位測(cè)試)
也是必備技能,畢業(yè)經(jīng)歷的四家外企,美企,德企,德企,瑞士企業(yè),沒(méi)有一家不寫UT的,中間在一個(gè)私企過(guò)渡了一下,呵呵,UT是什么?最近,小伙伴們?cè)趯慤T時(shí)遇到了各種問(wèn)題,借此機(jī)會(huì)我對(duì)UT做一個(gè)總結(jié),希望小伙伴們?cè)趯慤T時(shí)不要繞彎路。示例的源碼可以直接通過(guò)csdn下載也可以通過(guò)git導(dǎo)出:https://github.com/igdnss/mockito.git
注:這里主要是介紹Mockito的使用,所以需要有一定的junit test 的基礎(chǔ),文中關(guān)于junit test 不懂的地方歡迎評(píng)論,私信,第一時(shí)間解答。
- UnitTest 介紹
- 常用標(biāo)簽
- Mockito介紹
- 代碼介紹
- mock對(duì)象
- 深度mock對(duì)象
- mock方法調(diào)用
- 有返回值方法調(diào)用
- 拋出異常方法調(diào)用
- 無(wú)返回值方法調(diào)用
- 迭代方法調(diào)用
- thenAnswer處理業(yè)務(wù)邏輯
- mock對(duì)象調(diào)用真實(shí)方法
- spy 部分mock
- mock參數(shù)匹配
- isA()類型判斷
- any類型判斷
- 通配符的使用
- hamcrest 的使用
- 結(jié)束語(yǔ)
UnitTest 介紹
在介紹Mockito之前,強(qiáng)調(diào)Unit Test的幾點(diǎn)內(nèi)容。
其中第3天提到ut要獨(dú)立于外界資源,這看起來(lái)很奇怪,沒(méi)有外界資源ut怎么能跑起來(lái),這就是本篇要要介紹的重點(diǎn)。沒(méi)有外界資源,我們需要偽造出資源,也就是業(yè)內(nèi)所說(shuō)mock資源。目前可以提供mock的框架有很多,例如easymock,powermock以及本文要介紹了mockito。
常用標(biāo)簽
本篇主要介紹Mockito,順便將junit test中使用在方法上的標(biāo)簽也整理出來(lái),方便后面讀代碼。
@BeforeClass
在所有類執(zhí)行之前執(zhí)行,例如設(shè)置上下文環(huán)境,共享變量等。
@Before
在當(dāng)前類執(zhí)行之前執(zhí)行,例如初始化對(duì)象,變量等。
@After
在當(dāng)前類執(zhí)行之后執(zhí)行。
@AfterClass
在所有類執(zhí)行之后執(zhí)行
@Test
需要測(cè)試業(yè)務(wù)邏輯
@Test(timeout=xxx)
在timeout時(shí)間范圍內(nèi)如果沒(méi)有執(zhí)行完測(cè)試邏輯,則報(bào)錯(cuò)
@Test(expected=Exception.class)
設(shè)置當(dāng)前的測(cè)試邏輯拋出的異常,異常類型為Exception.class
@Ignore
忽略當(dāng)前的測(cè)試邏輯,不執(zhí)行
Mockito介紹
官網(wǎng): https://site.mockto.org 不太喜歡這個(gè)官網(wǎng),東西有點(diǎn)亂,但畢竟是官方的權(quán)威性,再亂也得硬著頭皮去看。mockito是一個(gè)測(cè)試框架,通過(guò)mock(模擬)外界資源讓測(cè)試代碼無(wú)需依賴真實(shí)環(huán)境就能跑起來(lái),可以理解為讓測(cè)試代碼在虛擬環(huán)境中跑起來(lái)。接下來(lái),我會(huì)將工作中常用到一些知識(shí)點(diǎn)全部整理出來(lái),希望能幫助大家。依賴于自己寫的一個(gè)簡(jiǎn)單三層架構(gòu)的示例進(jìn)行介紹,代碼的邏輯和環(huán)境很簡(jiǎn)單,沒(méi)有具體的數(shù)據(jù)庫(kù),沒(méi)有具體的業(yè)務(wù)邏輯,主要是為了介紹Mockito是如何將各個(gè)部分Mock出來(lái)并完成UT的。主要測(cè)試Controller層與Service層中的方法,有個(gè)別Mock的知識(shí)點(diǎn)可能沒(méi)有涉及到Demo中的方法,旨在介紹知識(shí)點(diǎn)。其中UnitTest和Mockito的版本分別為:4.13.2,1.10.19
注意:mockito mock的資源不能是局部的,例如局總變量,私有方法是無(wú)法mock的。
代碼介紹
Controller 層:
通過(guò)此層去調(diào)用業(yè)務(wù)層,實(shí)現(xiàn)根據(jù)id查找用戶的接口
Mapper層:
/*** 并沒(méi)有真正意義上去訪問(wèn)數(shù)據(jù)庫(kù)*/ public class UserMapper {public User findById(int userId) {throw new UnsupportedOperationException();} }domain層:
public class Base { } public class Client extends Base {} public class User extends Base{String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}**service層: **
public class UserService{UserMapper userMapper;public User findById(int userId) {User user = userMapper.findById(userId);return user;}public void clear() {throw new RuntimeException();}public List<User> getGroup() {throw new RuntimeException();}public int getAge() {return 18;}public int getAgeByIdAndName(int id,String name) {return 18;}public String getName(Base base) {throw new RuntimeException();}}以上代碼真的是一位含苞待放的姑娘,一切的一切都是那么的干凈清爽,在這些的代碼基礎(chǔ)之上我們對(duì)mockito進(jìn)行抽絲剝繭。
mock對(duì)象
三種最常用的方法。
使用此方法必須要在@RunWith(MockitoJUnitRunner.class)中傳入MockitoJUnitRunner.class 。這種法一般用于測(cè)試方法中局部對(duì)象的mock
示例
可以使用@Mock標(biāo)簽,一般mock全局對(duì)象。
示例
注:mock的對(duì)象只是一個(gè)空對(duì)象,其內(nèi)部的屬性并沒(méi)有mock出來(lái),所以直接使用mock的對(duì)象調(diào)用方法是會(huì)報(bào)空指針異常,因此使用mock的對(duì)象調(diào)用方法時(shí),還需要mock方法的調(diào)用。或者在@Before中加上MockitoAnnotaion.initMocks(this);
深度mock對(duì)象
FindingController getUser()方法中調(diào)用了UserService的getUser()返回結(jié)果為User,如果這需要測(cè)試user.getName(),就得再需要mock一個(gè)User 對(duì)象。可以使用深度mock來(lái)解決這個(gè)問(wèn)題。
@Mock(answer=Answers.RETURNS_DEEP_STUBS)//深度mockprivate UserService userService;mock方法調(diào)用
有返回值方法調(diào)用
語(yǔ)法一: when(T methodCall).thenReturn(T returnValue);
methodCall:方法調(diào)用;returnValue:調(diào)用此方法mock出的返回值。注:如果對(duì)象是mock出來(lái)的,必須要mock它的方法調(diào)用,否則會(huì)報(bào)空指針異常,因?yàn)閙ock的時(shí)候只mock一個(gè)空對(duì)象,其內(nèi)部的屬性并沒(méi)有mock出來(lái),所以報(bào)空指針異常。
語(yǔ)法二: doReturn(Object toBeReturned).when(T mock).方法 。
示例:
一步到位,無(wú)需多次mock
拋出異常方法調(diào)用
語(yǔ)法一: when(T methodCall).thenThrow(Class<? extends Throwable>… throwableClasses);這種方法已經(jīng)被derecated了,基本不用。
語(yǔ)法二: doThrow(Class<? extends Throwable> toBeThrown).when(T mock).方法;
示例:
無(wú)返回值方法調(diào)用
語(yǔ)法: doNothing().when(T mock).方法; 調(diào)用完方法后需要驗(yàn)證此方法是被調(diào)用的次數(shù)。verify(T mock, VerificationMode mode).方法。其中mode表示方法被調(diào)用的次數(shù),可以不傳,默認(rèn)為times(1)。
示例:
迭代方法調(diào)用
語(yǔ)法一: when(T methodCall).thenReturn(Object value,Object … values);
語(yǔ)法二: when(T methodCall).thenReturn(Object value,Object … values);
針對(duì)同一個(gè)方法,希望每一次的調(diào)用結(jié)果不同,就應(yīng)該用到此方法
示例:
thenAnswer處理業(yè)務(wù)邏輯
語(yǔ)法: when(T methodCall).thenAnswer(Answer<?> answer)
當(dāng)有一些結(jié)果為動(dòng)態(tài)結(jié)果時(shí),就要用這種方式了。
示例:
mock對(duì)象調(diào)用真實(shí)方法
語(yǔ)法: when(T methodCall).thenCallRealMethod();
使用mock對(duì)象調(diào)用真實(shí)的方法就需要使用到此種方式。注意:這里調(diào)用的方法不能是抽象方法
示例:
spy 部分mock
語(yǔ)法: Object o = spy(真實(shí)對(duì)象);
在有些測(cè)試場(chǎng)景下,需要測(cè)試真實(shí)對(duì)象的值,對(duì)部分只能使用mock來(lái)處理,可以借助spy來(lái)完成。
示例:
mock參數(shù)匹配
在前面的示例中提到參數(shù)匹配,就是當(dāng)調(diào)用一個(gè)方法時(shí),應(yīng)該返回什么樣的值。這里主要介紹一下以下幾種方式。
isA()類型判斷
示例:
測(cè)試getName()中傳入的是否為Base類型的對(duì)象
any類型判斷
這個(gè)方法我基本沒(méi)有用過(guò),感覺(jué)意義不大
示例:
通配符的使用
前文中使用過(guò)通配符anyInt(), Mockito中提供了好幾個(gè)通配符,這里舉兩個(gè)例子。使用通配符的時(shí)候一定要注意,參數(shù)列表中一處使用通配符,就得處處使用通配符,如果想傳入特定的值一定要使用eq()方法。通配符的優(yōu)先級(jí)大于eq(),如果同樣的方法多個(gè)mock,通配符寫在最后一句的話會(huì)覆蓋前面mock的結(jié)果。
示例:
hamcrest 的使用
hamcrest中提供了很多強(qiáng)大的功能,配合assertThat()使用會(huì)增加代碼的可讀性,代碼編寫風(fēng)格符合陳述式風(fēng)格。另外,可以不用使用assertTure(), assertEquals()等斷言方法,使用一個(gè)assertThat()就可以了。以下示例獨(dú)立于文章開頭的業(yè)務(wù)代碼。但assertThat已經(jīng)deprecated了,不知道為什么。
示例:
結(jié)束語(yǔ)
終于寫完了,真心不容易,不過(guò)挺開心。Mockito中常用點(diǎn)都在這里了,當(dāng)然Mockito中還有很多知識(shí)點(diǎn),大家可以參考官網(wǎng)。希望本文能幫助大家,祝大家在IT之路上少走彎路,一路綠燈不堵車,測(cè)試一性通過(guò),bug秒解!
總結(jié)
以上是生活随笔為你收集整理的欧美企业必备技能-Mockito的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: kafka消费端Attempt to h
- 下一篇: 什么是中间件?如何设计一个中间件?