试图用Groovy Spock mock:GroovyCastException模拟两个类
我尝试在Jenkins Pipeline var脚本中模拟两个类,但不管我如何安排模拟的定义,我收到一个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'
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模拟是一种代码味道。