2015-04-30 41 views
7

我遇到的問題是,當我嘗試在then塊中驗證已拋出異常並且已經進行模擬調用時。Spock通過模擬交互驗證異常拋出

看看下面的設置:

class B { 
    def b(A a) { 
     a.a() 
    } 
} 

class A { 
    def a() { 
    } 
} 

def "foo"() { 
    given: 
    def a = Mock(A) 
    a.a() >> { throw new RuntimeException() } 
    B b = new B() 

    when: 
    b.b(a) 

    then: 
    thrown(RuntimeException) 
    1 * a.a() 
} 

上述測試失敗消息:Expected exception java.lang.RuntimeException, but no exception was thrown,但代碼建立模擬明確地拋出異常。

有趣的是,如果你刪除最後一行:1 * a.a()測試通過。在當時沒有驗證異常的塊中放置另一個斷言時,我沒有類似的問題。

任何想法發生了什麼?

+0

雖然@歐泊爾的回答是正確的,我會問爲什麼這是一個好主意。一般來說(當然不是所有情況下,但很多情況下),只有當相關方法對測試代碼沒有直接影響時才需要驗證交互。返回值或拋出異常的方法確實如此。 –

+0

來自該問題的代碼受到一個真實案例的啓發,在該案例中,我想驗證是否調用了寫入數據庫的方法,並且如果引發錯誤,它將被傳播。這個特殊的例外可能有更多的原因,所以我需要驗證與模擬的交互是其原因。 – jarzeb

回答

10

應配置並通過以下方式進行驗證:

@Grab('org.spockframework:spock-core:0.7-groovy-2.0') 
@Grab('cglib:cglib-nodep:3.1') 

import spock.lang.* 

class Test extends Specification { 
    def "foo"() { 
     given: 
     def a = Mock(A) 
     B b = new B() 

     when: 
     b.b(a) 

     then: 
     thrown(RuntimeException) 
     1 * a.a() >> { throw new RuntimeException() } 
    } 
} 


class B { 
    def b(A a) { 
     a.a() 
    } 
} 

class A { 
    def a() { 
    } 
} 

如果同時模擬和驗證模擬的互動行爲應該在where/then塊進行配置。