我是3y,一年CRUD
經驗用十年的markdown
程序員👨🏻💻常年被譽爲職業八股文選手
最近在看單元測試的東西,想跟大家聊聊我的感受。單元測試這塊說實在的,我並不太熟悉,我幾乎不寫單元測試,也不太愛寫單元測試。
當我推廣消息推送平臺austin的時候,有過批評我整個項目沒有單元測試,也有過讓我補上單元測試的。
01、單元測試(UNIT TEST)
我有個前同事進了外企,他說進了外企以後學習了很多新名詞,剛進去時都不知道他們講的是什麼...
他問我:UT你知道是什麼意思嗎?
我說:不知道啊。
他說:UT是Unit Test,單元測試
我說:你們現在都要寫單元測試嗎?
他說:是啊
後來,我在羣裏閒聊的時候,發現有個企鵝上班的大哥也不知道UT是什麼意思,那我就放心了。
02、測試類型有什麼
測試類型對於我們開發人員來說,或許可以歸納分爲三類:
1、單元測試:對某個類中的代碼進行測試,查看是否正常
2、集成測試:跨模塊測試查看代碼是否正常
3、端到端測試:以用戶的角度把系統作爲一個整體看功能是否正常
所以,在我們程序員裏談單元測試的時候,可能會是純單元測試,也可能是集成測試,畢竟這塊大概率都應該是我們乾的。
03、爲什麼要單元測試
對於我這種不怎麼寫單元測試的,也不愛寫單元測試的,在我的嘴裏自然就編不出要寫單元測試的理由了,倒是不寫單元測試的理由是一堆堆的。
說到單元測試,就不得不提起另一個詞,TDD(Test-Driven Development)測試驅動開發:在開發功能代碼之前,先編寫單元測試用例代碼,測試代碼確定需要編寫什麼產品代碼
測試驅動開發雖然飽受爭議,不過有這種方法論的推出並有不少的同行在踐行,起碼能夠說明測試的重要性。
1、當我們想測試部分代碼邏輯是否正常的時候,我們可能會直接psvm
來構造數據進而調試。那如果有一種東西能把我們psvm
統一放到某個地方呢?
2、當我們在一個系統裏邊修改了很多代碼時,又不確定改動是否影響在覈心邏輯時。那如果有一種東西能在編譯的時候,順便自動跑一遍邏輯做迴歸呢?無論是重構還是正式提測前,都提高了自己寫代碼的信心。
3、當我們很容易一不小心時就把代碼寫成一坨屎,那如果有一種東西能讓我們在編碼的時候就注重自己的代碼設計呢?
4、當我們這個季度什麼都沒幹,但是系統沒發生過故障,那如果有一種東西能讓我們在KPI上添上濃墨的一筆呢?
5、....歡迎補充
沒錯,這東西就是單元測試。
04、單元測試怎麼寫?
很長一段時間裏,怎麼寫單元測試我的知識就停留在Junit上。後來,跟我那個進外企的小夥伴以及羣裏的滴滴哥交流了以後,發現他們都會用Mockito這個框架去寫單元測試
在這個過程中, 我看了些關於Mockito單元測試的文章,但總會有專業術語給我勸退,到這裏我就很明白,我要邊寫邊看了。
1、SpringBoot環境下使用Mockito只需要引入spring-boot-starter-test
就好了,默認內置了Mockito相關的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
2、我們單元測試是寫在對應的test目錄下的,想想都知道會有插件可以幫我們通過主類成爲出對應的測試類,是不需要我們手動去建包和建測試類的。
於是,我找到了squaretest插件
3、看幾篇Mockito相關的教程,瞭解其API和概念,推薦下這個教程: https://www.letianbiji.com/java-mockito/mockito-mock.html
4、親自動手寫一個單元測試,瞭解其編寫過程和感受體驗
有的人可能看到這裏就要問了:爲什麼要用Mockito這種測試框架而不是純用Junit? 在我的看來,答案就是:我們在測試時對象可能是Spring下的,我們不能直接new,又或是new出來的對象成本很大(還得解決依賴等問題)
這時候,我們就需要Mock對象出來模擬我們創建了這個對象,而在學習Mockito測試框架在這個過程中,其實就是對Mock/Stub/Spy概念的理解以及他們的使用。
Mock和Spy都是模擬創建出一個對象,區別在於Spy模擬創建出的對象是會真實調用方法的,而Mock模擬創建出的對象是不會真實調用方法的
那Mock模擬創建出來的對象不會調用真實方法,但我們又想驗證其流程怎麼辦?
比如,我在寫service
層的單元測試,我認爲dao
層的代碼是正常的,但是service
是需要dao
的對象訪問數據庫的,這時候我Mock出dao
的模擬對象,去調用方法。
所以我會假定調用dao
層的某方法時它的返回值是什麼,這個過程就是Stub
05、集成測試怎麼寫
在剛剛,我們使用Mockito的時候,是沒有依賴Spring環境的,對象都是Mock出來的,速度槓槓的,非常快。但我們很多時候可能是需要依賴Spring環境跨模塊去調試功能是否正常。
這時候,我們就要使用 @SpringTest來修飾測試類指明我這個是需要Spring環境的。既然有了Spring環境,那 @Autowire之類的註解都是可以用的。
在web模塊下啓動的話,你會發現它就真的啓動了應用相關的環境,然後專門跑了這個測試方法。
05、爲什麼我不愛寫單元測試
我是寫完了業務代碼,然後再回過頭來寫單元測試。單元測試是我自己寫的,我Mock出來模擬對象再Stub,整個過程中我都是認爲我寫的代碼是正確的。
寫完了以後,看到綠色的條框我並不意外,畢竟我是對着我的業務代碼寫的單元測試。而集成測試都把Spring環境相關的依賴都整進去了,我直接在本地啓動服務也能自己調呀。
(我相信看到這篇文章絕大多數人都不是TDD模式開發,應該都是對着自己寫好的業務代碼寫單元測試)
寫單元測試的代碼也是代碼,也是要花時間的呀
我也去問了騰訊/滴滴/阿里/字節的朋友,發現他們也不愛寫單測,很多時候寫單測就是爲了通過編譯,爲了業務的覆蓋率,能繞開就繞開了。
爲什麼沒有問京東/拼多多/美團/網易等等的?別問,問就是還沒太熟。
看到這篇文章的同行肯定是有在團隊推行寫單元測試的,不妨在評論區寫下理由拯救一下我們這些迷途不愛寫單元測試的羔羊。
如果想學Java項目的,我還是強烈推薦我的開源項目消息推送平臺Austin,可以用作畢業設計,可以用作校招,可以看看生產環境是怎麼推送消息的。
austin消息推送平臺項目源碼Gitee鏈接:gitee.com/austin
austin消息推送平臺項目源碼GitHub鏈接:github.com/austin