Groovy Spock正在验证模拟与模拟交互一起引发的异常

Groovy Spock正在验证模拟与模拟交互一起引发的异常,groovy,mocking,spock,Groovy,Mocking,Spock,我遇到的问题是,当我尝试在then块中验证是否抛出了异常,以及是否对模拟进行了调用时 请查看以下设置: 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()

我遇到的问题是,当我尝试在
then
块中验证是否抛出了异常,以及是否对模拟进行了调用时

请查看以下设置:

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()
}
上述测试失败,消息为:
预期异常java.lang.RuntimeException,但未引发异常
,但设置模拟的代码显式引发异常

有趣的是,如果删除最后一行:
1*a.a()
测试通过。我在then块中组合另一个断言时没有遇到类似的问题,该断言不验证异常


有什么想法吗?

应该按照以下方式进行配置和验证:

@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() {
    }
}

如果您同时模拟和验证交互,那么模拟行为应该在
中的
/
中配置,那么
块。

既然@Opal的答案是正确的,我想问为什么这是个好主意。通常(当然不是在所有情况下,而是在许多情况下),您只需要验证当所讨论的方法对测试代码没有直接影响时发生的交互。返回值或抛出异常的方法会返回值或抛出异常。问题中的代码受一个真实案例的启发,在这个案例中,我想验证是否调用了写入数据库的方法,如果抛出错误,则会传播错误。这个特殊的异常可能有更多的原因,所以我需要验证与mock的交互是否是导致该异常的原因。