试图用Groovy Spock mock:GroovyCastException模拟两个类

试图用Groovy Spock mock:GroovyCastException模拟两个类,groovy,spock,Groovy,Spock,我尝试在Jenkins Pipeline var脚本中模拟两个类,但不管我如何安排模拟的定义,我收到一个GroovyCastException,而第二个类的模拟是启动的 org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Mock for type 'ClassA'' with class 'com.pipeline.ClassA$$EnhancerByCGLIB$$9b005c28'

我尝试在Jenkins Pipeline var脚本中模拟两个类,但不管我如何安排模拟的定义,我收到一个GroovyCastException,而第二个类的模拟是启动的

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Mock for type 'ClassA'' with class 'com.pipeline.ClassA$$EnhancerByCGLIB$$9b005c28' to class 'com.pipeline.DBReader'
我的Spock测试是这样的:

import com.homeaway.devtools.jenkins.testing.JenkinsPipelineSpecification
import com.pipeline.ClassA
import com.pipeline.DBReader
import groovy.sql.Sql
import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException
import hudson.model.Result

class execScriptSpec extends JenkinsPipelineSpecification {
    def execPipelineScript = null

    def mockStage = [timeout: [time: 'mocktime']]
    def mockScript = [...]

def setup() {
    execPipelineScript = loadPipelineScriptForTest("vars/execScript.groovy")
}

def "Test Pipeline-Script"() {

    setup:

      GroovyMock(ClassA, global: true)
      new ClassA(*_) >> Mock(ClassA) {
        loadScope(_) >> null
        loadJsonFromURL(_) >> null
      }

      GroovyMock(DBReader, global: true)
      new DBReader(*_) >> Mock(DBReader) {
        loadDBDriver(_) >> null
      }
  when:
      execPipelineScript(mockScript, mockStage)
  then:
      true

这就是正在测试的代码:

import com.pipeline.DBReader
import com.pipeline.ClassA

def call(script, stage) {
  def pipelineConfig = script.pipelineConfig
  def stageStatus = pipelineConfig.general.stageStatus

  def projectName = script.env.project

  // DB connection parameters
  def dbName = script.deliveryConfig.system.dbName
  def dbSchema = script.deliveryConfig.system.dbSchema
  def dbServer = script.deliveryConfig.system.dbServer
  def dbUser = script.deliveryConfig.system.dbUser
  // DB Driver to use
  def dbDriver = script.deliveryConfig.system.dbDriver
  def dbPassword = script.env.password

  // Create new DB-Client
  DBReader dbClient = new DBReader(dbName, dbSchema, dbServer, dbUser, dbPassword, dbDriver)
  dbClient.loadDBDriver()
   
  def contextParameter = script.params['Context']

  ClassA mapGavToVersionRange = new ClassA(projectName, contextParameter, script)
  classAInstance.loadDeliveryScope( dbClient )
  def url = 'https://some.valid.url'
  classAInstance.loadJsonFromURL(url)

  ...
所以不要误解我的意思:对一个或另一个类的实际模拟是有效的(如果我在测试中只放了其中一个),但一旦我把它们都放进去,第二个就不起作用了。我现在不知道为什么会这样。 如果有人有主意,那就太好了:-)
非常感谢

为什么不让
ClassA
DBReader
可注入,而不是在
调用(…)
方法中创建它们呢?这样,您的代码将变得更易于测试,您就不需要像Groovy Mock这样的黑客解决方案。若您不想通过方法参数注入它们,那个么将实例创建提取到两个助手方法中,您可以轻松地将它们存根。解耦您的依赖关系,这是一个基本的设计原则,如果它“只是”一个小脚本的话。在如此简单的情况下必须使用Groovy Mock是一种代码味道。为什么不让
ClassA
DBReader
可注入,而不是在
调用(…)
方法中创建它们呢?这样,您的代码将变得更易于测试,您就不需要像Groovy Mock这样的黑客解决方案。若您不想通过方法参数注入它们,那个么将实例创建提取到两个助手方法中,您可以轻松地将它们存根。解耦您的依赖关系,这是一个基本的设计原则,如果它“只是”一个小脚本的话。在如此简单的情况下使用Groovy模拟是一种代码味道。