Technically, tail()
isn't being called on the list object (ArrayList
doesn't declare such a method). Therefore, the proxy-based Spy()
doesn't get a chance to intercept the call. Try with GroovySpy()
.
Spock spy registers too few invocations (none) of Groovy method
-
24-09-2022 - |
Question
I have written a Groovy extension library that adds extra methods to the List class. I am trying to write tests for this using Spock but I am unable to get some of my tests to work.
The code
There are a number of methods that all have the same form. I have added methods that work the same as tail()
(or head()
, first()
, etc.) but that will just return null
if the List is empty, rather than throwing an Exception. An example is shown below (println()s added for troubleshooting):
public static def tailIfAny(List list) {
println "tailIfAny() list.size(): ${list.size()}"
def r = list.size() ? list.tail() : null
println "r: $r"
return r
}
I want to have two tests for tailIfAny()
. The first test should check that no exception is thrown if you call the method on an empty List. This was straightforward and works. The other test I want to write is to check that tail()
is called if the list is not empty.
The test
This is my test to check that tail()
is called if the List is not empty:
def "tailIfAny() calls tail()"() {
setup:
def list = Spy(ArrayList)
list << 'a'
list << 'b'
when:
println "list ${list} -- ${list.size()}"
println "Before tailIfAny()"
list.tailIfAny()
println "After tailIfAny()"
then:
1 * list.tail()
}
The error message
When I run me tests I get this failure message:
Too few invocations for: 1 * list.tail() (0 invocations) Unmatched invocations (ordered by similarity): 1 * list.toArray() 1 * list.iterator() 3 * list.size() 1 * list.isEmpty() at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:78) at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:76) at com.fgi.extensions.ListExtensionsTests.add element in setup(ListExtensionsTests.groovy:65)
But from the stdout output (below) I can see that tail()
should have been called.
The standard out from the tests
list [a, b] -- 2 Before tailIfAny() tailIfAny() list.size(): 2 r: [b] // This tells me that tail() is being called. After tailIfAny()
Can anyone shed some light on why Spock thinks that tail()
isn't being called? or is there something going on here that I'm missing?
Thanks.
Solution