使用Spock框架進(jìn)行單元測(cè)試

使用Spock框架進(jìn)行單元測(cè)試 - OPEN 開(kāi)發(fā)經(jīng)驗(yàn)庫(kù)
http://www.open-open.com/lib/view/open1439793373083.html
很多人一談到單元測(cè)試就會(huì)想到xUnit框架。對(duì)于一些java新人來(lái)說(shuō),會(huì)用jUnit就是會(huì)寫單元測(cè)試,高級(jí)點(diǎn)的會(huì)搗鼓一下testng,然后就認(rèn)為自己掌握了單元測(cè)試。

2.2.單元測(cè)試的痛點(diǎn)
對(duì)于新人來(lái)說(shuō),很容易在編寫單元測(cè)試的時(shí)候遇到這幾類問(wèn)題:
2.2.1.單元測(cè)試的資料不夠全
這里不夠全是相對(duì)于“編碼”來(lái)說(shuō)的。介紹如何編碼、如何使用某個(gè)框架的書茫茫多,但是與編碼同樣重要的介紹單元測(cè)試的書卻不多,翻來(lái)覆去好的也不多,并且都有一定年頭了。(如果有這方面的好的資料,請(qǐng)推薦給我,多謝)
很多關(guān)于編程的書籍中并沒(méi)有深入介紹如何進(jìn)行單元測(cè)試,或者僅僅介紹了最基礎(chǔ)的assert、jUnit里怎么定義一個(gè)測(cè)試函數(shù)之類,就沒(méi)有然后了,給人的感覺(jué)是這樣:
[圖片上傳中。。。(1)]
2.2.2.單元測(cè)試難以理解和維護(hù)
測(cè)試代碼不像普通的應(yīng)用程序一樣有著很明確的作為“值”的輸入和輸出。舉個(gè)例子,假如一個(gè)普通的函數(shù)要做下面這件事情:
接收一個(gè)user對(duì)象作為參數(shù)
調(diào)用dao層的update方法更新用戶屬性
返回true/false結(jié)果

那么,只需要在函數(shù)中聲明一個(gè)參數(shù)、做一次調(diào)用、返回一個(gè)布爾值就可以了。但如果要對(duì)這個(gè)函數(shù)做一個(gè)“純粹的”單元測(cè)試,那么它的輸入和輸出會(huì)有很多情況,比如其中一個(gè)測(cè)試是這樣:
假設(shè)調(diào)用dao層的update方法會(huì)返回true。
程序去調(diào)用service層的update方法。
驗(yàn)證一下service是不是也返回了true。

無(wú)論是用什么樣的單元測(cè)試框架,最后寫出來(lái)的單元測(cè)試代碼量也比業(yè)務(wù)代碼只多不少,我在寫代碼過(guò)程中的經(jīng)驗(yàn)值是:要在不作弊的情況下維持比較高的單元測(cè)試覆蓋率,要有三倍于業(yè)務(wù)代碼的單測(cè)代碼。
更多的代碼量,加上單測(cè)代碼并不像業(yè)務(wù)代碼那樣直觀,還有對(duì)單測(cè)代碼可讀性不重視的壞習(xí)慣,導(dǎo)致最終呈現(xiàn)出來(lái)的單測(cè)代碼難以閱讀,要維護(hù)更是難上加難。
同時(shí),大部分單元測(cè)試的框架都有很強(qiáng)的代碼侵入性。要理解單元測(cè)試,首先得學(xué)習(xí)他用的那個(gè)單元測(cè)試框架,這無(wú)形中又增加了單元測(cè)試?yán)斫夂途S護(hù)的難度。
2.2.3.單元測(cè)試難以去除依賴
就像之前說(shuō)的,如果要寫一個(gè)純粹的、無(wú)依賴的單元測(cè)試往往很困難,比如依賴了數(shù)據(jù)庫(kù)、或者依賴了文件系統(tǒng)、再或者依賴了其它模塊。
所以很多人在寫單元測(cè)試時(shí)選擇依賴一部分資源,比如在本機(jī)啟動(dòng)一個(gè)數(shù)據(jù)庫(kù)。這類所謂的“單元測(cè)試”往往很流行,但是對(duì)于多人合作的項(xiàng)目,這類測(cè)試卻經(jīng)常容易造成混亂。
比如說(shuō)要在本地讀個(gè)文件,或者連接某個(gè)數(shù)據(jù)庫(kù),其他修改代碼的人(或者持續(xù)集成系統(tǒng)中)并沒(méi)有這些東西,所以測(cè)試也都沒(méi)法通過(guò)。最后大部分這類測(cè)試代碼的下場(chǎng)都是用不了、也舍不得刪,只好被注釋掉,扔在那里。
隨著開(kāi)源項(xiàng)目逐漸發(fā)展,對(duì)外部資源的依賴問(wèn)題開(kāi)始可以通過(guò)一些測(cè)試輔助工具解決,比如使用內(nèi)存型數(shù)據(jù)庫(kù)H2代替連接實(shí)際的測(cè)試數(shù)據(jù)庫(kù),不過(guò)能替代的資源類型始終有限。
而實(shí)際工作過(guò)程中,還有一類難以處理的依賴問(wèn)題:代碼依賴。比如一個(gè)對(duì)象的方法中調(diào)用了其它對(duì)象的方法,其它對(duì)象又調(diào)用了更多對(duì)象,最后形成了一個(gè)無(wú)比巨大的調(diào)用樹。
很多比較舊的描述單元測(cè)試的書里寫了一些傳統(tǒng)的辦法,這類方法基本上是先對(duì)耦合的部分做模擬,再對(duì)結(jié)果部分做斷言。例如可以通過(guò)繼承來(lái)自己做一個(gè)假的stub對(duì)象,最終用assert的方式驗(yàn)證正確性。但是這相當(dāng)于對(duì)于每種假設(shè)都要做一個(gè)假的對(duì)象,而且對(duì)結(jié)果進(jìn)行驗(yàn)證也比較復(fù)雜:比如我要驗(yàn)證“更新”操作是否真的調(diào)用了dao層,那么要自己在stub對(duì)象里對(duì)調(diào)用進(jìn)行計(jì)數(shù),驗(yàn)證時(shí)再對(duì)計(jì)數(shù)進(jìn)行斷言,非常繁瑣。
后來(lái)出現(xiàn)了一些mock框架,比如java的JMockit、EasyMock,或者M(jìn)ockito。利用這類框架可以相對(duì)比較輕松的通過(guò)mock方式去做假設(shè)和驗(yàn)證,相對(duì)于之前的方式有了質(zhì)的飛躍,但是即使用上這類框架,遇到復(fù)雜的業(yè)務(wù)代碼往往也無(wú)能為力。
而往往新人的代碼質(zhì)量往往不高,尤其是對(duì)代碼的拆分和邏輯的抽象還處于懵懂階段。要對(duì)這類代碼寫單測(cè),即使是工作了3,4年的高級(jí)碼農(nóng)也是一個(gè)挑戰(zhàn),對(duì)新人來(lái)說(shuō)幾乎是不可能完成的任務(wù)。這也讓很多新人有了“寫單測(cè)很難”的感覺(jué)。
所以在這里需要強(qiáng)調(diào)一個(gè)觀點(diǎn),寫單元測(cè)試的難易程度跟代碼的質(zhì)量關(guān)系最大,并且是決定性的。項(xiàng)目里無(wú)論用了哪個(gè)測(cè)試框架都不能解決代碼本身難以測(cè)試的問(wèn)題,所以如果你遇到的是“我的代碼里依賴的東西太多了所以寫不出來(lái)單測(cè)”這樣的問(wèn)題的話,需要去看的是如何設(shè)計(jì)和重構(gòu)代碼,而不是這篇文章。


在Spring Boot項(xiàng)目中使用Spock框架 - 簡(jiǎn)書
http://www.itdecent.cn/p/f1e354d382cd
利用Spock、Mockito一起編寫一些測(cè)試用例(包括對(duì)Controller的測(cè)試和對(duì)Repository的測(cè)試),感受下Spock的使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容