从 Spock 1.3 (groovy 2.4) 迁移到 2.x (groovy 4.0) Spy 不再适用于需要参数的构造函数

问题描述 投票:0回答:1

在 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()

与副驾驶交谈,问题似乎出在关闭委托上,我可以通过几种方法解决这个问题

  • 为字段实现 getter(添加
    def getSteps() { return steps }
  • 将委托设置为
    this
c = { steps.method() }
c.delegate = this
c.() // ok

我之前还没有查看过 Spock 1.3 v 2.0 的 Spy 案例中的委托类是什么。这样做后我会更新这个问题

groovy spock
1个回答
1
投票

我不知道你的问题是什么,因为你的代码不完整,也不知道为什么你想更新到过时的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 中尝试一下。

© www.soinside.com 2019 - 2024. All rights reserved.