如何在Spock中模拟特定于域的闭包

Gre*_*rin 5 email grails multipart spock

我想测试使用grails电子邮件插件发送电子邮件的Grails控制器.我不知道如何模仿sendMail闭包以便交互工作.这是我最新版本的测试代码:

def 'controller should send a multipart email'() {
    given: 'a mocked mailService'
        controller.mailService = Mock(grails.plugin.mail.MailService)
        controller.mailService.sendMail(*_) >> Mock(org.springframework.mail.MailMessage)
    when:
        controller.sendNow()
    then:
        1* _.multipart(true)
}
Run Code Online (Sandbox Code Playgroud)

控制器代码看起来像您期望的那样,例如:

def mailService
def sendNow() {
    mailService.sendMail {
        multipart true
        to 'example@example.org'
        from 'me@here.com'
        subject 'a subject'
        body 'a body'
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我运行这个测试,我得到0次调用我的multipart交互而不是1. given:块的第二行似乎对我很可疑,但如果我试图模拟一个Closure而不是org.springframework.mail.MailMessage我的测试崩溃.我还应该提到控制器本身按预期工作(它不能等我先弄清单元测试).

编辑

啊啊,几个小时之后用新鲜的头脑看着代码,我可以看出为什么上面的代码不起作用; 为了让我捕获multipart和其他DSL调用,我将不得不模拟闭包本身,而不是sendMail方法(我不能这样做,因为闭包是在控制器本身内定义的).我大概可以做的是检查参数的sendMail方法来查看所需的一切传递到它.

Lui*_*ñiz 3

您可以安装greenMail插件,并在集成测试中使用它:

从 greenmail 插件主页:

import com.icegreen.greenmail.util.*

class GreenmailTests extends GroovyTestCase {
    def mailService
    def greenMail    

    void testSendMail() {
        Map mail = [message:'hello world', from:'from@piragua.com', to:'to@piragua.com', subject:'subject']        

        mailService.sendMail {
            to mail.to
            from mail.from
            subject mail.subject
            body mail.message
        }        

        assertEquals(1, greenMail.getReceivedMessages().length)        
        def message = greenMail.getReceivedMessages()[0]        
        assertEquals(mail.message, GreenMailUtil.getBody(message))
        assertEquals(mail.from, GreenMailUtil.getAddressList(message.from))
        assertEquals(mail.subject, message.subject)
    }    

    void tearDown() {
        greenMail.deleteAllMessages()
    }
}
Run Code Online (Sandbox Code Playgroud)

我不是 Spock 专家,但您应该能够将这个 junit 测试转换为 Spock 风格。

来源: http: //grails.org/plugin/greenmail

更新,通过模拟 sendMail 替代

这是对 Gregor 更新的回答。在我看来,您必须模拟 sendMail 方法,并且在该方法内部有一个存根来实现闭包中使用的不同属性和方法。我们称其为评估器。您将初始化闭包的委托给 evaluatro,并执行闭包。评估者应该有断言。您会看到我在这里使用了更多的 junit 概念。我不知道你能多么容易地将其转化为 spock 概念。您可能能够使用 spock 的行为检查工具。

class MailVerifier {
    void multiPart(boolean v){
        //...
    }

    void to(String address){
        //...
    }

    boolean isVerified() {
        //check internal state obtained by the appropriate invocation of the methods
    }
}

def sendMail(Closure mailDefintion) {
    def evaluator = createMailVerifier()
    mailDefinition.delegate = evaluator

    mailDefinition()

    assert evaluator.verified
}
Run Code Online (Sandbox Code Playgroud)

  • @lucke84我最终得到了这个:https://gist.github.com/gregopet/7aedd77f4cf638fa31a9 (2认同)