4
votes

I'm testing error handling. I want the first call to mockedObject.foo() to throw a new IOException, and the second to return bar. I tried the following code,

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

But, when I run the test, I get an error stating that a closure cannot be cast to Bar,

FooSpec$_$spock_feature_0_1_closure2 cannot be cast to Bar

How can I mock this behavior with Spock?

EDIT: After seeing the documentation referenced by tim_yates, I just changed the test to,

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

This comes close enough to testing what I needed to test. The following code threw the same exception, so I'm guessing Spock is setting the return type of the mocked method based on the first object return.

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

3 Answers

3
votes

You should be able to do:

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

(See here in the documentation)

1
votes

Here, a complete working example:

@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
    }
}
0
votes

You can try to split the 'then' block:

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

.... (some other invoke assertions)

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

I know this topic is old, but maybe somebody still wants to find the solution for it. (Spock test: throw exception or value based on Invocation Order) Please refer to : https://spockframework.org/spock/docs/1.0/interaction_based_testing.html Invocation Order part