Spock:如何在规范的实现之间正确共享功能

CBl*_*lew 3 testing groovy spock

我遇到了 Spock Framework (1.3-groovy-2.5) 的一个不幸的方面,我用它来集成测试 Gradle 插件。

代码示例

家长班级:

class ClassA extends Specification {

    def setupSpec() {
        System.out.println("In ClassA setupSpec()")
    }

    def "base feature"() {
        expect:
        true
    }
}
Run Code Online (Sandbox Code Playgroud)

儿童班:

class ClassB extends ClassA {

    @Override
    def setupSpec() {
        System.out.println("In ClassB setupSpec()")
    }

    def "extended feature"() {
        expect:
        true
    }
}
Run Code Online (Sandbox Code Playgroud)

当我在 中运行测试时ClassB,两个版本都会setupSpec()被调用:

In ClassA setupSpec()
In ClassB setupSpec()
Run Code Online (Sandbox Code Playgroud)

当然,如果我通过本机 Groovy 方式调用方法:

class Main {

    static void main(String[] args) {
        ClassB classB = new ClassB()
        classB.setupSpec()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我只看到预期的内容:

In ClassB setupSpec()
Run Code Online (Sandbox Code Playgroud)

显然,这是 Spock 的某种功能。

问题

Specification在实践中,从重写设置逻辑的实现继承的建议方法是什么?

Leo*_*ngs 6

如夹具方法调用顺序中所述

如果在规范子类中重写了固定方法,则超类的 setup() 将在子类的 setup() 之前运行。cleanup() 的工作顺序相反,即子类的 cleanup() 将在超类的 cleanup() 之前执行。setupSpec() 和 cleanupSpec() 的行为方式相同。无需显式调用 super.setup() 或 super.cleanup(),因为 Spock 会自动查找并执行继承层次结构中所有级别的固定方法。

最简单的方法是将逻辑移动到您可以覆盖的另一个方法。

class Base extends Specification {
  def setupSpec() {
    init()
  }
  
  def init() {
    println "foo"
  }

  def "let's try this!"() {
    expect:
    Math.max(1, 2) == 2
  }
}


class Sub extends Base {
  @Override
  def init() {
    println "bar"
  }
}
Run Code Online (Sandbox Code Playgroud)