今天繼續(xù)聊下spock 的其他特性,如果沒有看到前面的內(nèi)容胸梆,可以點(diǎn)擊這里查看前面的介紹。
1.Mocking
1.1 什么是Mocking
Mocking是一種改變我們的服務(wù)與我們的服務(wù)合作的類的行為的方式须板。 這是一種有效的方法碰镜,可以獨(dú)立測試業(yè)務(wù)邏輯的依賴關(guān)系。
一個(gè)典型的例子就是用一個(gè)簡單的假裝來替換一個(gè)網(wǎng)絡(luò)調(diào)用的類习瑰。
5.2. 用spock 來 Mocking
Spock擁有自己的模擬框架绪颖,利用了Groovy帶給JVM的有趣概念。 首先甜奄,我們來實(shí)例化一個(gè)Mock:
PaymentGateway paymentGateway = Mock()
在這種情況下菠发,我們的模擬類型是由變量類型推斷的。 由于Groovy是一種動(dòng)態(tài)語言贺嫂,我們還可以提供一個(gè)類型參數(shù)滓鸠,使我們不必將模擬分配給任何特定的類型:
def paymentGateway = Mock(PaymentGateway)
現(xiàn)在,無論何時(shí)我們在PaymentGateway模擬中調(diào)用方法第喳,都會(huì)給出默認(rèn)響應(yīng)糜俗,而不會(huì)調(diào)用實(shí)際的實(shí)例:
when:
def result = paymentGateway.makePayment(12.99)
then:
result == false
這個(gè)術(shù)語是lenient mocking
。 它的意思是未定義的模擬方法將返回合理的默認(rèn)值曲饱,而不是拋出異常悠抹。 這是在Spock中設(shè)計(jì)的,目的是為了使模擬和測試更加健壯扩淀。
1.3 在Mocks上調(diào)用樁方法
我們也可以配置我們的Mock
上調(diào)用的方法以某種方式響應(yīng)不同的參數(shù)楔敌。 讓我們嘗試讓我們的PaymentGateway
模擬在我們支付20時(shí)返回true
:
given:
paymentGateway.makePayment(20) >> true
when:
def result = paymentGateway.makePayment(20)
then:
result == true
這里有趣的是,Spock如何利用Groovy的操作符重載來樁方法調(diào)用驻谆。 對于Java卵凑,我們必須調(diào)用真正的方法,這可能意味著生成的代碼更加冗長胜臊,并且可能不那么富有表現(xiàn)力勺卢。
現(xiàn)在,讓我們嘗試更多類型的樁象对。
如果我們停止關(guān)注我們的方法參數(shù)并始終想要返回true黑忱,則可以使用下劃線:
paymentGateway.makePayment(_) >> true
如果我們想要在不同的響應(yīng)之間進(jìn)行切換,我們可以提供一個(gè)列表,每個(gè)元素將依次返回:
paymentGateway.makePayment(_) >>> [true, true, false, true]
1.4 驗(yàn)證
我們可能想要用Mock來做的另一件事是斷言有不同的方法在預(yù)期的參數(shù)上被調(diào)用甫煞。 換句話說菇曲,我們應(yīng)該驗(yàn)證與我們的模擬的交互。驗(yàn)證的典型用例是如果我們的模擬方法有無效返回類型抚吠。
在這種情況下羊娃,由于沒有結(jié)果讓我們操作,所以我們沒有推測的行為可以通過測試方法進(jìn)行測試埃跷。
一般來說蕊玷,如果返回了一些東西,那么被測試的方法就可以對它進(jìn)行操作弥雹,這就是我們斷言的操作結(jié)果垃帅。讓我們試著驗(yàn)證一個(gè)帶有void返回類型的方法:
def "Should verify notify was called"() {
given:
def notifier = Mock(Notifier)
when:
notifier.notify('foo')
then:
1 * notifier.notify('foo')
}
Spock正在利用Groovy運(yùn)算符重載。 通過將我們的模擬方法調(diào)用乘以一剪勿,我們說我們期望它被調(diào)用了多少次贸诚。
如果我們的方法根本沒有被調(diào)用或者沒有按照我們指定的次數(shù)被調(diào)用,那么我們的測試將沒有給我們提供一個(gè)信息量很大的Spock錯(cuò)誤消息厕吉。 讓我們通過期待它被調(diào)用兩次來證明這一點(diǎn):
2 * notifier.notify('foo')
在此之后酱固,讓我們看看錯(cuò)誤消息是什么樣的。 我們會(huì)像往常一樣; 這是相當(dāng)豐富的:
Too few invocations for:
2 * notifier.notify('foo') (1 invocation)
就像樁
一樣头朱,我們也可以執(zhí)行更寬松的驗(yàn)證匹配运悲。 如果我們不關(guān)心我們的方法參數(shù)是什么,我們可以使用下劃線:
2 * notifier.notify(_)
或者如果我們想確保它沒有被特定參數(shù)調(diào)用项钮,我們可以使用not操作符:
2 * notifier.notify(!'foo')
總結(jié)
結(jié)合之前的文章班眯,我們通過使用Spock進(jìn)行測試給出了一些小的分片案例,展示了Spock比典型的JUnit更具表現(xiàn)力烁巫。
我們已經(jīng)展示了執(zhí)行數(shù)據(jù)驅(qū)動(dòng)測試是多么容易署隘,以及通過本地Spock功能如何輕松模擬和斷言。更多的Spock的特性亚隙,請查看官方文檔磁餐。
歡迎大家繼續(xù)關(guān)注。