bgarrels / spock

Automatically exported from code.google.com/p/spock
0 stars 0 forks source link

Unable to define mock behavior and verify interactions in the same test #355

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I attempted to define the behavior of a method for a mock object and verify 
it's interaction in the same test, but ran into a series of problems. I was 
able to create a simplified example of the issues I ran into here: 
http://meetspock.appspot.com/script/5750085036015616

Essentially, I tried to verify that a method returned a value that was also 
passed into a call to a dependency. I mocked that dependency and tried to use 
the following syntax to verify it:
when:
  def value = myClass.doStuff()

then:
  1 * myClass.dependency.method(value)

Apparently, spock does not allow accessing the 'value' in the 'then' block. I 
then tried mocking the dependency's 'method' to keep track of what value was 
stored, but I found that this mock method was never called. Removing the 
verification in the 'then' block allowed for my mock method to be called, when 
leads me to believe that Spock does not allow you to use both in the same test.

I'm using Grails 2.2.4... I'm not sure what versions of Spock and Groovy are 
used with that,

Original issue reported on code.google.com by abl...@commercehub.com on 28 Mar 2014 at 9:07

GoogleCodeExporter commented 9 years ago
The core problem is that Spock verifies interactions as they happen, not after 
the fact. (An interaction declared in a then-block is effectively moved to a 
setup-block.) And at the time `method` is called, `doStuff` hasn't yet returned 
a value. To solve this problem, you'll need to capture the value passed to 
`method`, and compare it to the value returned from `doStuff` in an assertion. 
For further information, see http://docs.spockframework.org.

Original comment by pnied...@gmail.com on 29 Mar 2014 at 6:39

GoogleCodeExporter commented 9 years ago
Using your advice, I came up with the following that works. Is this what you 
had in mind? It seems to only work if `valueUsedByDoStuff` is declared in the 
'given' block.

def "what was suggested by Spock maintainer"() {
    given:
        String valueUsedByDoStuff
        MyClass myClass = new MyClass()
        myClass.dependency = Mock(MyDependency)

    when:
        String value = myClass.myMethod()

    then: "doStuff is called once with the value returned from myMethod"
        1 * myClass.dependency.doStuff({ valueUsedByDoStuff = it })
        valueUsedByDoStuff == value
  }

Original comment by abl...@commercehub.com on 29 Mar 2014 at 5:35