【问题标题】:Unit testing a void method: verifying arguments单元测试 void 方法:验证参数
【发布时间】:2015-05-31 00:45:11
【问题描述】:

我正在为我的程序创建一个单元测试。我有一个 void 方法,它接受五个参数,然后将这些参数转换为闭包并将其传递给另一个服务以转换为电子邮件并发送。我唯一关心的是这封电子邮件的正文,它存储在传递给此函数的参数之一中。是否可以在不改变我的程序设计的情况下验证这个论点?

我考虑过使用 Spock 风格的模拟,但我无法确定我是否可以在经过规范测试的类中实际模拟/存根方法,或者我是否只能模拟依赖项。

一个简化的例子

Class myTestService
{
    def outsideService
    private void sendEmail (User source, String subj, String body, List to, List attachments){
       outsideService.sendMail{
           //blah blah
           subject subj
           html wrapWithDefault(body) //wrapWithDefault is a big styling document also in this function
           //blah blah
           }
       }

int send(GrailsParameterMap params, HttpServletRequest request) {
      //Parse out attachments from request and body/subject/addressee from params
      //little bit of business logic to ensure that we can send emails in our system
      sendEmail(source,
                subject,
                "$body <br /><br /> important extra information", 
                sendTo,
                attachments)

      //Send another email to the source as a receipt
      sendEmail(source,
                subject,
                "$body extra junk $receiptBody",
                source,
                attachments)
   }

}

我需要确定收据是否正确添加了receiptBody。鉴于我正在向 outsideService 发送一个闭包,因此很难从中提取变量,所以我有点茫然。

编辑:为了响应下面的答案,我在测试中插入了一个 spock 风格的模拟,但我认为我的语义不正确,因为 value 正在存储 null。 void "#value 包含 #params.body"() { 给定:

   //def params, request, filling in all necessary values

   def value
   def mailServiceMock = Mock(MailService)
   mailServiceMock.sendMail(*_) >> {closure ->
        closure.delegate = new Expando(
            multipart:{},
            from: {},
            subject: {},
            html: {value = it}
            bcc: {}
            )
        closure()
   }
   //inform service of mock
   service.mailService = mailServiceMock

   when:
       service.send(params, request)
   then:
   println("value = $value")
   1 * mailServiceMock.sendMail(*_) // this should fail, since this should be called twice, but one thing at a time.
   value.contains(params.body)

   }

值显示为空。有什么想法吗?

【问题讨论】:

    标签: unit-testing grails groovy spock


    【解决方案1】:

    您可以模拟您的服务。

    这是一个非常简单的脚本,它模拟outsideService 以将html 方法中接收到的值存储在脚本变量中。你应该去找 Spock/JUnit/YouNameIt 来整理一下。

    class MyTestService
    {
        def outsideService
        private void sendEmail (source, String subj, String body, List to, List attachments){
           outsideService.sendMail{
               subject subj
               html "<body>$body</body>"
           }
       }
    }
    
    
    myTest = new MyTestService()
    
    def body
    myTest.outsideService = [sendMail: { closure ->
      closure.delegate = new Expando(
        subject: { }, //don't care
        html: { body = it }
      )
      closure()
    }]
    
    myTest.sendEmail(null, 'my subject', 'my email body', null, null) 
    assert '<body>my email body</body>' == body
    

    【讨论】:

    • 我使用 spock 风格的模拟更新了我的问题,我没有得到正确的输出值(在你的例子中是正文)你的代码有效,但我不确定我的代码在哪里失去功能。
    • 使用元类改变了功能。具体实施。不过,您的答案适用于我的测试用例,因此您的答案是正确的。不知道为什么我的示例没有转化为工作代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多