Spock 簡(jiǎn)介,一個(gè)比Junit豐富的測(cè)試框架 (part 3)

今天繼續(xù)聊下spock 的其他特性,如果沒有看到前面的內(nèi)容,可以點(diǎn)擊這里查看前面的介紹。

1.Mocking

1.1 什么是Mocking

Mocking是一種改變我們的服務(wù)與我們的服務(wù)合作的類的行為的方式。 這是一種有效的方法,可以獨(dú)立測(cè)試業(yè)務(wù)邏輯的依賴關(guān)系。

一個(gè)典型的例子就是用一個(gè)簡(jiǎn)單的假裝來(lái)替換一個(gè)網(wǎng)絡(luò)調(diào)用的類。

5.2. 用spock 來(lái) Mocking

Spock擁有自己的模擬框架,利用了Groovy帶給JVM的有趣概念。 首先,我們來(lái)實(shí)例化一個(gè)Mock:

PaymentGateway paymentGateway = Mock()

在這種情況下,我們的模擬類型是由變量類型推斷的。 由于Groovy是一種動(dòng)態(tài)語(yǔ)言,我們還可以提供一個(gè)類型參數(shù),使我們不必將模擬分配給任何特定的類型:

def paymentGateway = Mock(PaymentGateway)

現(xiàn)在,無(wú)論何時(shí)我們?cè)赑aymentGateway模擬中調(diào)用方法,都會(huì)給出默認(rèn)響應(yīng),而不會(huì)調(diào)用實(shí)際的實(shí)例:

    when:
    def result = paymentGateway.makePayment(12.99)
 
then:
    result == false

這個(gè)術(shù)語(yǔ)是lenient mocking。 它的意思是未定義的模擬方法將返回合理的默認(rèn)值,而不是拋出異常。 這是在Spock中設(shè)計(jì)的,目的是為了使模擬和測(cè)試更加健壯。

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的操作符重載來(lái)樁方法調(diào)用。 對(duì)于Java,我們必須調(diào)用真正的方法,這可能意味著生成的代碼更加冗長(zhǎng),并且可能不那么富有表現(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來(lái)做的另一件事是斷言有不同的方法在預(yù)期的參數(shù)上被調(diào)用。 換句話說(shuō),我們應(yīng)該驗(yàn)證與我們的模擬的交互。驗(yàn)證的典型用例是如果我們的模擬方法有無(wú)效返回類型。

在這種情況下,由于沒有結(jié)果讓我們操作,所以我們沒有推測(cè)的行為可以通過測(cè)試方法進(jìn)行測(cè)試。

一般來(lái)說(shuō),如果返回了一些東西,那么被測(cè)試的方法就可以對(duì)它進(jìn)行操作,這就是我們斷言的操作結(jié)果。讓我們?cè)囍?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)用乘以一,我們說(shuō)我們期望它被調(diào)用了多少次。

如果我們的方法根本沒有被調(diào)用或者沒有按照我們指定的次數(shù)被調(diào)用,那么我們的測(cè)試將沒有給我們提供一個(gè)信息量很大的Spock錯(cuò)誤消息。 讓我們通過期待它被調(diào)用兩次來(lái)證明這一點(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)行測(cè)試給出了一些小的分片案例,展示了Spock比典型的JUnit更具表現(xiàn)力。

我們已經(jīng)展示了執(zhí)行數(shù)據(jù)驅(qū)動(dòng)測(cè)試是多么容易,以及通過本地Spock功能如何輕松模擬和斷言。更多的Spock的特性,請(qǐng)查看官方文檔。

歡迎大家繼續(xù)關(guān)注。

?著作權(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)容