首页 > 解决方案 > 返回的模拟对象具有所有导致测试失败的空字段

问题描述

我有一个使用名为 ReportingService 的服务的简单类。它被注入到类中,我正在验证它是否被调用并带有预期的参数。模拟通过确保 reportType 和其他值符合预期,返回我想在测试中断言的 ReportSummary 对象。不幸的是,ReportSummary 字段都是空的,我做错了什么?

class ReportSummary {
   String reportType
   Date createdTime
   String reportedById 
} 
class ReportingService {
   ReportSummary updateReport(Report reportData) {
       ...
   }
}

该服务被注入到一个类 PricingService 中,如下所示:

   class PricingService {
       @Autowired
       ReportingService reportingService

       ReportingSummary updatePricingDetails( ReportData data) {
           reportingService.updateReport(data)
       }
  }

该类在这样的服务中使用

class PricingServiceSpec extends Specification {

   ReportingService reportingService = Mock()
   PricingService pricingService = new PricingService( reportingService)
   ReportData  data = new ReportData(........)       

   def "Should return summary report data" (){
     given:       
     Date today = new Date (System.currentMillis())

     ReportSummary summary = new ReportSummary(reportType: 'Pricing',createdTime:           
     today, reportedById: 'GXT111111345')
  
     when:
  
     ReportSummary response = pricingService.updatePricingDetails(data)

     then:
     1 * reportingService.updateReport( data : {
   
     assert it.pricingDescription == 'Pricing for Produce'
  
     }) >> summary
  
     response.reportType == 'Pricing'  // The reportType is null why?
     response.reportedById == 'GXT111111345'   // The reportById is null, why? The 
     0 * _       
    )       
   }
 }

标签: unit-testinggroovyspock

解决方案


这是一些示例代码,它至少可以编译并模拟您的情况,即使它返回一些虚拟数据(但至少与您要测试的存根结果不同):

package de.scrum_master.stackoverflow.q67912725

class ReportData {
  String pricingDescription;
}
package de.scrum_master.stackoverflow.q67912725

class ReportSummary {
  String reportType
  Date createdTime
  String reportedById
}
package de.scrum_master.stackoverflow.q67912725

class ReportingService {
  ReportSummary updateReport(ReportData reportData) {
    return new ReportSummary(
      reportType: "real report",
      createdTime: new Date(),
      reportedById: "me"
    )
  }
}
package de.scrum_master.stackoverflow.q67912725

import org.springframework.beans.factory.annotation.Autowired

class PricingService {
  @Autowired
  ReportingService reportingService

  ReportSummary updatePricingDetails(ReportData data) {
    reportingService.updateReport(data)
  }
}

这是一个通过测试。您的基本问题是您试图在方法约束中使用方法参数名称,即在您的原始代码中data :断言闭包之前的部分。方法参数按类型和位置匹配,而不是按参数名称。忽略它,你很好。

顺便说一句,您也不应该assert在方法参数约束中使用,而是一个简单的布尔表达式。一个失败的断言会使测试失败,这不是你想要的。您只是想匹配一个参数值。

修复测试对我来说并不难。我花了 10 倍的时间才真正编译这个烂摊子并做一些合乎逻辑的事情,甚至开始分析测试。

package de.scrum_master.stackoverflow.q67912725

import spock.lang.Specification

class PricingServiceTest extends Specification {
  def reportingService = Mock(ReportingService)
  def pricingService = new PricingService(reportingService: reportingService)
  def reportData = new ReportData(pricingDescription: 'Pricing for Produce')

  def "Should return summary report data"() {
    given:
    ReportSummary stubbedSummary = new ReportSummary(
      reportType: 'Pricing',
      createdTime: new Date(),
      reportedById: 'GXT111111345'
    )

    when:
    ReportSummary reportSummary = pricingService.updatePricingDetails(reportData)

    then:
    1 * reportingService.updateReport(
      { it.pricingDescription == 'Pricing for Produce' }
    ) >> stubbedSummary
    reportSummary.reportType == stubbedSummary.reportType
    reportSummary.reportedById == stubbedSummary.reportedById
    0 * _
  }
}

推荐阅读