在 Spockframework 1.3 中,以下工作适用于间谍,然后间谍对象创建一个闭包 MyClass 是闭包的委托。在 Spock 2.0 中,闭包不会将 MyClass 设置为其委托。
instance = (MyClass) Spy(
MyClass,
constructorArgs: [env, steps])
类将env和steps存储为this.env、this.steps。它没有定义 getEnv() 或 getSteps()
该类实际上用于 JenkinsShared 库,因此该步骤实际上是 vars groovy 文件的“this”对象,该对象提供对库源类中的管道方法的访问。
class JenkinsStepAccess{
{
public def env
public def steps
BaseClass(def env, def steps) {
this.env = env
this.steps = steps
}
}
class DynamoDbManager extends JenkinsStepAccess {
DynamoDbManager(def env, def steps) {
super(env, steps)
}
def doThing() {
// failing code as within the closure
// this class is not the delegate automatically
// in the newer Spock version, but is in the older
def c = { this.steps.readFile(filePath)}
def result = c()
}
}
该项目将 JenkinsSci Pipeline Unit 和 SpockFramework 连接在一起,并且必须更改委托才能执行此操作。然而,鉴于上下文是正交的,我怀疑这就是问题所在。
class PipelineTestHelper extends BasePipelineTest {
// in this class we use PipelineUnit to replace Jenkins pipeline methods with our own
// For instance readFile() gets replaced with our definition etc. The content of this
// class should not be important as the problem seems to relate to the classes under test
// and this class isn't the spock class
}
class PipelineSpockTestBase extends Specification implements RegressionTest{
/**
* Delegate jenkins DSL to the helper class
*/
@Delegate PipelineTestHelper pipelineTestHelper
...
// again the majorty of this class methods aren't involved the the failure
// they mainly are conveniance methods
}
class DynamoDbManagerTest extends PipelineSpockTestBase {
// class under test
DynamoDbManager dynamoDbManager
@BeforeEach
void setup() {
dynamoDbManager = (DynamoDbManager) Spy(DynamoDbManager, constructorArgs: [env, steps])
}
def thingTest() {
given:
... not important ...
when:
dynamoDbManager.doThing('script text')
...
}
在 2.0 中,当任何内容引用时,该步骤就会失败,并出现以下错误:
No signature of method: MyClass.getSteps()
is applicable for argument types: () values: []
该错误似乎仅在闭包内 Spy 对象尝试访问由构造函数更新的字段时才会发生。
// OK
steps.method()
// Failure
c = { steps.method() }
c()
与副驾驶交谈,问题似乎出在关闭委托上,我可以通过几种方法解决这个问题
def getSteps() { return steps }
)this
c = { steps.method() }
c.delegate = this
c.() // ok
我之前还没有查看过 Spock 1.3 v 2.0 的 Spy 案例中的委托类是什么。这样做后我会更新这个问题
我不知道你的问题是什么,因为你的代码不完整,也不知道为什么你想更新到过时的Spock 2.0而不是最新的2.4-M4。您也没有提及您使用的是哪个 Groovy 版本。我尝试使用 2.4-M4-groovy-4.0,您所描述的问题似乎工作正常:
package de.scrum_master.stackoverflow.q78318941
class Steps {
def method() {}
}
package de.scrum_master.stackoverflow.q78318941
class BaseClass {
def env
Steps steps
BaseClass(def env, Steps steps) {
this.env = env
this.steps = steps
}
void foo() {
bar('foo')
}
void bar(String s) {
def c = { steps.method() }
c()
}
}
package de.scrum_master.stackoverflow.q78318941
class MyClass extends BaseClass {
MyClass(def env, Steps steps) {
super(env, steps)
}
}
package de.scrum_master.stackoverflow.q78318941
import spock.lang.Specification
class MyClassTest extends Specification {
def test() {
given:
def env = 'my env'
Steps steps = Mock()
def instance = (MyClass) Spy(MyClass, constructorArgs: [env, steps])
when:
instance.foo()
then:
1 * instance.bar('foo')
1 * steps.method()
}
}
这在 Spock 1.3 和 2.4-M4 中都工作得很好。
在 Groovy Web Console 中尝试一下。