3

I'm trying to validate that this groovy closure in a class called CUTService has the correct values:

mailService.sendMail {
    to '[email protected]'
    from '[email protected]'
    subject 'Stuff'
    body 'More stuff'
}

I've looked at https://github.com/craigatk/spock-mock-cheatsheet/raw/master/spock-mock-cheatsheet.pdf, but his syntax produces an error:

1 * mailService.sendMail({ Closure c -> c.to == '[email protected]'})

groovy.lang.MissingPropertyException: No such property: to for class: com...CUTService

I've looked at Is there any way to do mock argument capturing in Spock and tried this:

1 * mailService.sendMail({closure -> captured = closure })
assertEquals '[email protected]', captured.to

which produces:

groovy.lang.MissingPropertyException: No such property: to for class: com...CUTService

I also tried this:

1 * mailService.sendMail({captured instanceof Closure })
assertEquals '[email protected]', captured.to

which produces:

Too few invocations for:
1 * mailService.sendMail({captured instanceof Closure })   (0 invocations)

...

Unmatched invocations (ordered by similarity):
1 * mailService.sendMail(com...CUTService$_theMethod_closure5@21a4c83b)

What do I need to do to get this working?

Community
  • 1
  • 1
Don Branson
  • 13,631
  • 10
  • 59
  • 101

1 Answers1

6

When you write :

mailService.sendMail {
    to '[email protected]'
    from '[email protected]'
    subject 'Stuff'
    body 'More stuff'
}

In fact, you are executing the method sendMail, with a closure c. sendMail create a delegate, and call your closure with this delegate. Your closure is in reality executed as :

delegate.to('[email protected]')
delegate.from('[email protected]')
delegate.subject('Stuff')
delegate.body('More stuff')

To test this closure, you should create a mock, configure the delegate of your closure to this mock, invoke the closure, and verify the mock expectation.

As this task is not really trivial, it's better to reuse the mail plugin and create his own mail builder :

given:
  def messageBuilder = Mock(MailMessageBuilder)

when:
   // calling a service

then: 
    1 * sendMail(_) >> { Closure callable ->
      callable.delegate = messageBuilder
      callable.resolveStrategy = Closure.DELEGATE_FIRST
      callable.call(messageBuilder)
   }
   1 * messageBuilder.to("[email protected]")
   1 * messageBuilder.from("[email protected]")
Jérémie B
  • 10,611
  • 1
  • 26
  • 43