單元測試
一個穩定的系統少不了單元測試,單元測試(又稱為模塊測試, Unit Testing)是針對程序模塊(軟件設計的最小單位)來進行正確性檢驗的測試工作。
對於面向對象編程,最小單元就是方法,包括父類、抽象類、或者子類中的方法。
所以單元測試的特點:
- 測試的是一個代碼單元內部的邏輯,而不是各模塊之間的交互。
- 無依賴,不需要實際運行環境就可以測試代碼。
- 運行效率高,可以隨時執行。
而單元測試的應用場景一般主要有這幾個:
- 測試驅動開發,由於工期限制,幾乎無法實現
- 對每次代碼修改做回歸測試
spock測試框架
簡介
Spock是基於JUnit的單測框架,提供一些更好的語法,結合Groovy語言,可以寫出更為簡潔的單測,它的語法完全遵循 BDD(行為驅動開發) 風格的結構。同時集成了像 Jmock、Mockito 等語法表達風格於一體,使得它很簡潔有很高的可讀性
與其他單元測試框架對比
Spock相比JUnit有易讀、簡潔、自帶Mock等特性,可以減少單元測試編寫時間,而且bug更少,可讀性更好,寫出的單元測試代碼更優雅,更易於閱讀!
Spock提供了覆蓋Java企業應用的完整的測試生命周期。其他框架,是基於某種需要產生的,比如:Junit單純用於單測,但不提供mock;Mockito提供mock功能,但不提供靜態類的mock;PowerMock提供靜態類mock;
它們之間需要整合,且不容易跟上新的測試場景。Spock提供了全家桶測試,內置了mock和stub功能等,很方便上手
特點
- 全能,高效,代碼簡介,易讀,方法名支持中文
- 提供Groovy的closures,類似Java8的lambda表達式
- Mockito對參數匹配有限制。如果在方法中使用匹配器,那么所有的參數都需要匹配器。Spock不受此限制,可以將實參與實參匹配器混合和匹配
- Spock區分了Stub和Mock,讓單測更易讀
- Spock提供了更多詳細的錯誤信息
基礎
關於依賴
依賴如果版本對不上會報各種各樣的錯,所以最好是根據maven倉庫中查看版本,一定要對應上:
比如如果是3.0版本的spock-core,groovy依賴就必須是:

基本用法
需要創建groovy類使用spock,所有的類都要繼承Specification類,如下:
class SpockDemoSpec extends Specification{
/**
* 在第一個測試方法開始前執行一遍
*/
def setupSpec() { println "------------ setupSpec: 所有測試開始之前執行 ------------" }
/**
* 每個測試方法開始前都會執行一遍
*/
def setup() { println "------------ setup:每個測試方法開始之前執行 ------------" }
/**
* 每個測試方法后都會執行一遍
*/
def cleanup() { println "------------ cleanup:每個測試方法結束之后執行 ------------" }
/**
* 最后一個測試方法后執行
*/
def cleanupSpec() { println "------------ cleanupSpec: 所有測試方法結束之后執行 ------------" }
def "測試given-expect"() {
given:
def a = new Random().nextInt(10)
def b = 2
expect:
println a
a > b
}
def "測試where"() {
expect:
result == ++id
// where表格 左邊是參數,右邊是測試結果
where:
id | result
10 | 11
100 | 101
1000 | 1001
}
def "測試given-when-then"() {
given:
// 數據准備
def a = "houzheng"
when:
// 條件判斷
boolean flag = a.equals("houzheng")
then:
// 期望結果
flag
}
def "測試異常thrown"() {
when:
// 此方法會拋出RuntimeException
throw new RuntimeException("模擬異常");
then:
// 接收異常
def ex = thrown(Exception)
ex.class.name == "java.lang.RuntimeException"
ex.getMessage() == "模擬異常"
}
}
Demo執行結果:

- where: 以表格的形式提供測試數據集合
- when: 觸發行為,比如調用指定方法或函數
- then: 做出斷言表達式
- expect: 期望的行為,when-then的精簡版
- given: mock單測中指定mock數據
- thrown: 如果在when方法中拋出了異常,則在這個子句中會捕獲到異常並返回
- def setup() {} :每個測試運行前的啟動方法
- def cleanup() {} : 每個測試運行后的清理方法
- def setupSpec() {} : 第一個測試運行前的啟動方法
- def cleanupSpec() {} : 最后一個測試運行后的清理方法
springboot中的使用
常用注解
項目中實際使用
筆者目前項目中某個業務的使用
與原來單元測試代碼的對比
打包運行
測試報告輸出
心得體會與總結
- 兼容性比較差,依賴版本稍微不對,就會報一些莫名其妙的錯誤,而且提示也不明顯,不太好排查
- 其實雖然說要懂groovy,但是懂java的人還是非常容易上手的,只要給一個demo,基本就能夠寫單測了
- 如果還想寫的更優雅更高級,那可以去學學groovy,這里放一下筆者的鏈接:https://www.cnblogs.com/houzheng/p/15183586.html , 有興趣可以看看
