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.

Was it helpful?

Solution

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().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top