Spock雖然好用,但要應用到實際項目中還是需要注意幾個問題,下面講下我們公司在使用過程中遇到的一些問題和解決方案
要使用Spock首先需要引入相關依賴,目前使用下來和我們項目相容的Spock版本是1.3-groovy-2.5,以maven為例(gradle可以參考官網),完整的pom依賴如下:
Spock是使用groovy語言寫單測的,是以需要引入groovy-all的依賴
在引入 groovy-all 包時排除了 groovy-test-junit5 和 groovy-testng,這兩個包和和 power mock 有沖突,在執行 mvn test 會導緻NPE的問題
如果你的項目中沒有用過groovy,還需要添加groovy的maven編譯插件,這樣才能編譯我們用Spock寫的單元測試
引入groovy依賴後可能會出現版本沖突的問題,因為如果你的項目引用了springboot-start-base這樣的集合式jar包,它裡面也會引用groovy,有可能跟我們引入的groovy包版本出現沖突,或者公司的一些架構也會引用groovy的包,如果版本不一緻也有可能沖突,需要排下包,如果沒有沖突,可以忽略
然後執行 mvn clean compile 驗證下是否有沖突,如果能成功編譯就沒有這個問題
目前Spock的最新版本是2.0以上,在Spock 2.x 的版本裡官方團隊已經移除Sputnik,不再支援代理運作power mock的方式
因為Spock 2.0是基于JUnit5,我們項目以前的單元測試代碼都是基于Junit4編寫的,換成Junit5後,需要修改現有的java單測,比如指定代理運作,使用power mock的地方要換成Junit5的擴充文法
對現有使用Junit4 + power mock/jmockit的方式改變較大,為降低遷移成本沒有使用最新的Spock2.X版本
如果你的項目之前就是使用Junit5寫單測的,那麼可以使用Spock2.X的版本,2.0以上版本使用power mock可以參考官方提供的解決方案:

(https://github.com/spockframework/spock/commit/fa8bd57cbb2decd70647a5b5bc095ba3fdc88ee9)
後續我也會優先在我的部落格(www.javakk.com)推出 Spock2.x 版本的使用教程
編譯(mvn clean compile)通過之後,用spock編寫的groovy類型的單測代碼不能放在原來的test/java目錄下面
因為按照groovy的約定,預設編譯groovy包下的單測,是以需要建個groovy檔案夾存放spock的單測代碼,如下圖所示:
這樣也友善區分原來Java單測和用Spock寫的單測代碼
另外記得别忘了标記groovy目錄為測試源目錄(Test Source Root),如下圖:
(groovy檔案夾右鍵 → Mark Directory as → Test Sources Root)
第一次運作spock單測代碼時如果提示"no test suite exist"的錯誤,可以右鍵recompile下
還有記得建立的單測檔案類型是Groovy Class,不是Java Class類型
最後使用intellij idea的快捷鍵建立單元測試,在需要測試的類或方法上右鍵IDE的菜單,選擇"Go To → Create New Test" 選擇我們已經建立好的groovy檔案夾:
這樣就自動生成了groovy類型的單測檔案
執行mvn test,按照上面兩步的配置保證spock單測代碼運作成功後可以執行mvn clean test指令,跑一下這個項目的單測用例
(這一步不是必須的,但如果公司加了單測覆寫率的統計時,在cicd系統釋出時或merge request to release代碼合并到release分支時,會先執行mvn test類似的指令,確定所有的單元測試運作成功)
如果你的項目和我們一樣既有Java單測又有Spock單測,需要確定兩種單測都能執行成功(目前我們項目的spock單測和java單測在公司的CICD系統以及git上都能相容和通過測試覆寫率要求)
另外按照Spock的規範,單測代碼檔案的命名應該是以Spec為字尾的,如果你嚴格按照這個規範命名單測檔案,比如"OrderServiceSpec.groovy",那麼需要在maven-surefire-plugin測試插件裡添加以Spec為字尾的配置:
但是我是直接使用IDE生成單元測試,intellij idea自動生成的單測字尾還是“Test”,是以不存在這個問題,如果你也是這樣,忽略這個問題
Spock雖然使用友善,但還是要遵循單元測試的規範來,比如單元測試一般是針對方法或類的次元去測試的,也就是說我們關注的重點是目前類或方法内部的邏輯
如果目前被測方法依賴了其他層或module的邏輯,最好mock掉,盡量不要跨層測試,這屬于功能測試或內建測試的範疇
比如使用@SpringBootTest注解,預設會把目前方法依賴的下一層引用也注入@Autowired進來,其實完全可以交給Spock去管理,可以不需要SpringBootTest
後續如果新的問題或注意事項會持續更新
END -