尝试在单元测试中验证Groovy闭包

Don*_*son 3 groovy unit-testing spock

我正在尝试验证名为CUTService的类中的这个groovy闭包是否具有正确的值:

mailService.sendMail {
    to 'hey@example.com'
    from 'hey@example.com'
    subject 'Stuff'
    body 'More stuff'
}
Run Code Online (Sandbox Code Playgroud)

我查看了https://github.com/craigatk/spock-mock-cheatsheet/raw/master/spock-mock-cheatsheet.pdf,但他的语法产生错误:

1 * mailService.sendMail({ Closure c -> c.to == 'hey@example.com'})

groovy.lang.MissingPropertyException: No such property: to for class: com...CUTService
Run Code Online (Sandbox Code Playgroud)

我看过有没有办法在Spock中进行模拟参数捕获并试过这个:

1 * mailService.sendMail({closure -> captured = closure })
assertEquals 'hey@example.com', captured.to
Run Code Online (Sandbox Code Playgroud)

产生:

groovy.lang.MissingPropertyException: No such property: to for class: com...CUTService
Run Code Online (Sandbox Code Playgroud)

我也试过这个:

1 * mailService.sendMail({captured instanceof Closure })
assertEquals 'hey@example.com', captured.to
Run Code Online (Sandbox Code Playgroud)

产生:

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)
Run Code Online (Sandbox Code Playgroud)

为了让这个工作,我需要做什么?

Jér*_*e B 5

当你写:

mailService.sendMail {
    to 'hey@example.com'
    from 'hey@example.com'
    subject 'Stuff'
    body 'More stuff'
}
Run Code Online (Sandbox Code Playgroud)

实际上,您正在sendMail使用闭包c 执行该方法.sendMail创建一个委托,并使用此委托调用您的闭包.您的关闭实际上执行如下:

delegate.to('hey@example.com')
delegate.from('hey@example.com')
delegate.subject('Stuff')
delegate.body('More stuff')
Run Code Online (Sandbox Code Playgroud)

要测试此闭包,您应该创建一个mock,将闭包的委托配置到此mock,调用闭包,并验证模拟期望.

由于此任务不是很简单,因此最好重用邮件插件并创建自己的邮件生成器:

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("hey@example.com")
   1 * messageBuilder.from("hey@example.com")
Run Code Online (Sandbox Code Playgroud)