在使用Spock时,如何在多个返回结果中抛出IOException。

5

我正在进行错误处理的测试。我希望第一次调用 mockedObject.foo() 时抛出一个新的 IOException,第二次调用时返回 bar。我尝试了以下代码:

mockedObject.foo() >>> [{throw new IOException()}, bar]

但是,当我运行测试时,出现一个错误,指出闭包无法转换为Bar,

FooSpec$_$spock_feature_0_1_closure2无法转换为Bar

我该如何使用Spock模拟这种行为?

编辑:在看到tim_yates引用的文档后,我只需将测试更改为:

mockedObject.foo() >>> firstBar >> {throw new IOException()} >> secondBar

这基本上接近了我需要测试的内容。以下代码抛出了相同的异常,因此我猜测Spock是根据第一个对象返回来设置模拟方法的返回类型。

mockedObject.foo() >>> {throw new IOException()} >> secondBar
3个回答

6

谢谢提供文档链接。不幸的是,我用那段代码得到了相同的结果。 - Matt_Bro
被测试的 foo() 方法长什么样子? - tim_yates
'foo()'没有经过测试。被测试的方法基本上是通过调用foo并处理错误来循环执行的。 - Matt_Bro
@Matt_Bro 确保在 foo() 调用中匹配参数。如果您不关心参数,则最安全的方法是使用 mockedObject.foo(*_) >>> {throw new IOException()} >> bar。请注意,在模拟时使用 *_。如果 foo 有一个参数,则 mockedObject.foo(_) >>> {throw new IOException()} >> bar 应该可以工作。 - dmahapatro
从文档上看,三重右移运算符是用于值数组的。链接值(除了闭包和bar之外)“通常”应该按预期工作。 - ScientificMethod
这会抛出相同的异常。 - Matt_Bro

1
这里是一个完整的工作示例:
@Grab('org.spockframework:spock-core:0.7-groovy-2.0')
@Grab('cglib:cglib:3.1') 
@Grab('org.ow2.asm:asm-all:5.0.3') 

import spock.lang.*

class MyTestSpec extends Specification {    
   def 'spec'() {
      given:
      def a = new A()
      a.b = Mock(B) {
         foob() >> { throw new Exception('aaa') } >> 1
      }

      when:
      a.fooa()

      then:
      def e = thrown(Exception)        
      e.message == 'aaa'

      when:
      def r = a.fooa()

      then:
      r == 1
   }
}

class A {

    B b = new B()

    Integer fooa() {
        b.foob()
    }
}

class B {
    Integer foob() {
        2
    }
}

1

你可以尝试拆分'then'块:

then: 1 * mockedObject.foo() >> {throw new IOException()}

....(一些其他的调用断言)

then: 1 * mockedObject.foo() >> bar.

我知道这个话题很老了,但也许还有人想找到解决方案。 (Spock测试:根据调用顺序抛出异常或值) 请参考:https://spockframework.org/spock/docs/1.0/interaction_based_testing.html Invocation Order部分


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接