【问题标题】:Spock verifying an exception thrown by mock together with mock interactionSpock 与 mock 交互一起验证 mock 抛出的异常
【发布时间】:2015-07-10 02:30:24
【问题描述】:

我遇到的问题是,当我尝试在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()
}

上述测试失败并显示消息:Expected exception java.lang.RuntimeException, but no exception was thrown,但设置模拟的代码显式抛出异常。

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

有什么想法吗?

【问题讨论】:

  • 虽然@Opal 的回答是正确的,但我会质疑为什么这是个好主意。通常(当然不是在所有情况下,但在很多情况下),您只需要验证是否发生了交互,即相关方法对被测代码没有直接影响。返回值或抛出异常的方法确实如此。
  • 问题中的代码受到一个真实案例的启发,在该案例中,我想验证是否调用了写入数据库的方法,如果抛出错误,则会传播它。该特定异常可能有更多原因,因此我需要验证与模拟的交互是否是它的原因。

标签: groovy mocking spock


【解决方案1】:

应通过以下方式进行配置和验证:

@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 块中配置模拟行为。

【讨论】:

    猜你喜欢
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多