首页 > 解决方案 > Spock:如何在规范的实现之间正确共享功能

问题描述

我遇到了 Spock 框架 (1.3-groovy-2.5) 的一个不幸方面,我将其用于 Gradle 插件的集成测试。

代码示例

父类:

class ClassA extends Specification {

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

    def "base feature"() {
        expect:
        true
    }
}

儿童班:

class ClassB extends ClassA {

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

    def "extended feature"() {
        expect:
        true
    }
}

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

In ClassA setupSpec()
In ClassB setupSpec()

当然,如果我通过原生 Groovy 方式调用方法:

class Main {

    static void main(String[] args) {
        ClassB classB = new ClassB()
        classB.setupSpec()
    }
}

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

In ClassB setupSpec()

因此,显然,这是某种 Spock 功能。

问题

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

标签: testinggroovyspock

解决方案


夹具方法调用顺序中所述

如果在规范子类中覆盖了夹具方法,则超类的 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"
  }
}

推荐阅读