11

In our Spock tests we want to check if the correct path in our software is selected. But we do not want to test the function of the methods which are called (this is done in separate tests)

def "Test"() {
    setup:
    service.metaClass.innerMethod = { -> return null }

    when:
    service.doSomething("notexisting@test.com")

    then:
    1 * service.innerMethod(*_)
}

This test always fails, because the code in the innerMethod is called and the invocations of the method calls in the innerMethod are counted and not the invocation of the method innerMethod

|  Too few invocations for:
    1 * service.innerMethod(*_)   (0 invocations)

Unmatched invocations (ordered by similarity):

    1 * secondService.doSomething()

How can I just get the invocation of innerMethod and mock the complete function away?

Alexander Kiefer
  • 546
  • 1
  • 13
  • 30

1 Answers1

17

If you are not mocking the service itself, you would need to do something like this (be aware of passing the proper parameters when using metaClass:

def "Test"() {
    setup:
        def calls = 0
        service.metaClass.innerMethod = { p1 -> calls++ }
    when:
        service.doSomething("notexisting@test.com")
    then:
        calls==1
}

and if you are mocking the service,

def "Test"() {  
    when:
        service.doSomething("notexisting@test.com")
    then:
        1 * service.innerMethod(_)
}
Fran García
  • 2,011
  • 16
  • 24
  • Thanks for the hint. We will use the first method, as the service calls are within the same service and therefore are not mocked. – Alexander Kiefer Mar 27 '14 at 09:33
  • I tried doing the metaClass thing, and it didn't work until I added the parameter type, like so: `service.metaClass.innerMethod = { SomeClass p1 -> calls++ }` – stemadsen May 16 '18 at 12:47
  • Yes, that is normal, when overriding a method using the metaclass property, the signature should be exactly the same. – Fran García May 16 '18 at 13:12