單元測試新手上路——個人實踐總結(jié)
最近在做安全生產(chǎn)專項,寫了很多單測case。由于之前的工作中沒有很強(qiáng)制要求寫單元測試,一般是由測試人員去寫自動化測試,因此對單測的寫法不是很熟。在參考其他項目中的測試用例后,慢慢開始嘗試寫,這個過程中,也積累和總結(jié)了一些個人的經(jīng)驗,在此分享出來,歡迎大家指正和補(bǔ)充。
前言:為什么要寫單測?
軟件要易于修改
最近在看一本書《代碼整潔之道:程序員的職業(yè)素養(yǎng)》,這本書里面說到,代碼設(shè)計要遵循一個重要的原則-易于修改,并且要實現(xiàn)這個目標(biāo)就應(yīng)該經(jīng)常修改它,而不是等到大量積累了臃腫代碼之后再進(jìn)行深度重構(gòu)。
一套完善的測試用例是修改代碼的安全保障
而如何保證在頻繁修改優(yōu)化代碼之后,不影響其原本的功能呢?那就是要編寫一套完善的測試用例,能覆蓋到所有的鏈路場景,通過測試用例的執(zhí)行結(jié)果來確保代碼修改的正確性。
特別是我們做金融場景業(yè)務(wù)的開發(fā),尤其要注意代碼的正確性、安全性,那么寫好單測是不可或缺的。
一、寫單測前要做的準(zhǔn)備
了解你的業(yè)務(wù)流程
寫單測的基本前提是,你得足夠熟悉你要測試的鏈路流程,正常執(zhí)行的流程,以及異常及相應(yīng)處理。
另外,還需要清楚,什么樣的結(jié)果能代表代碼流程按預(yù)期執(zhí)行了,比如對方法返回結(jié)果的斷言,對數(shù)據(jù)庫生成記錄的校驗等。
梳理外部交互及數(shù)據(jù)變動點
如:
對外RPC調(diào)用
MQ消息的發(fā)送、消費
對數(shù)據(jù)庫的插入、修改、刪除
二、使用Mockito進(jìn)行Mock
Mockito注解
Mockito提供了幾個注解,包括@Mock、@Spy、@MockBean、@SpyBean,用于聲明式地構(gòu)造待Mock對象,只有被Mockito代理的對象才能進(jìn)行后續(xù)的方法行為mock。
@Spy 和 @SpyBean的區(qū)別、@Mock 和 @MockBean的區(qū)別
@Spy 和 @Mock 生成的對象不受Spring管理,而 @SpyBean 和 @MockBean 會生成SpringBean,可進(jìn)行自動注入。
@Spy 調(diào)用真實方法時,其依賴的其它bean是無法通過Spring自動注入的,要使用注入,要使用 @SpyBean
@MockBean 和 @SpyBean 的區(qū)別
默認(rèn)行為的不同:對于未指定mock的方法,spy默認(rèn)會調(diào)用真實的方法,有返回值的返回真實的返回值,而mock默認(rèn)不執(zhí)行,有返回值的,默認(rèn)返回null。
對于某些待測類,如果我們只想Mock其某一個方法,而其他方法希望按原來正常調(diào)用,那么就應(yīng)該使用@Spy或@SpyBean,而對于想要完全屏蔽原本行為的類,則使用@Mock或@MockBean來聲明。
注意:使用@MockBean時,通過Mockito.when().thenReturn()來模擬方法返回,但是使用@SpyBean時,這樣寫會調(diào)到真實的方法,需要Mockito.doReturn().when().xxx()來聲明模擬。
像我們目前在Springboot框架環(huán)境下開發(fā)的話,一般使用@MockBean和@SpyBean即可
Mock對象行為
Mock方法返回值
// 聲明userService在傳入任意參數(shù)調(diào)用get()方法時,返回user Mockito.when(userService.get(Mockito.any())).thenReturn(user); Mockito.doReturn(user).when(userService).get(Mockito.any()); // Spy必須用這種
Mock異常拋出
// 聲明userService在傳入任意參數(shù)調(diào)用get()方法時,拋出指定異常 Mockito.when(userService.get(Mockito.any())).thenThrow(new RuntimeException("mock error")); Mockito.doThrow(new RuntimeException("mock error")).when(userService).get(Mockito.any()); // Spy必須用這種
其他的Mock編寫可參考官方文檔:MockitoDoc
三、寫單測的注意點
每個用例聚焦測試方法的內(nèi)部邏輯,不關(guān)注外部及上下游
比如轉(zhuǎn)賬接口的單測,我應(yīng)該主要關(guān)注同步接口中的受理過程,受理流程完成后的異步過程,最好不要在當(dāng)前流程中提現(xiàn),而應(yīng)該另外再對異步實際調(diào)用方法寫Case。
消息消費和定時任務(wù)最好是針對最后實際調(diào)用的Service方法進(jìn)行測試。
單測不能影響外部應(yīng)用和數(shù)據(jù)
對外請求的Rpc調(diào)用要Mock掉,如果業(yè)務(wù)流程會根據(jù)對外調(diào)用的結(jié)果有所變化,要在多個Case中分別Mock不同的返回結(jié)果
避免對非測試數(shù)據(jù)和服務(wù)的影響
關(guān)閉Mq消息生產(chǎn)和消費
排除消息中間件配置類,這樣Producer和Consumer都不會初始化:
關(guān)閉Dubbo服務(wù)注冊
視情況關(guān)閉定時任務(wù)
Mock的數(shù)據(jù)要有標(biāo)識性
單元測試
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。