Spock 元编程 getProperty()

Spock Metaprogramming getProperty()

根据 get/setProperty 的文档,我想在 Spock 测试中覆盖 getProperty() 方法。这在正常的 Groovy class 中是微不足道的,但在 Spock 规范中似乎不起作用。

class MainSpec extends Specification {
    @Override
    def getProperty(String name) {
        def value = metaClass.getProperty(this, name)
        println "$name == $value"
        return value
    }

    String foo = 'foo'

    def test() {
        expect:
        foo
        println foo
    }
}

此示例不调用 getProperty() 方法。看起来 Spock 正在以某种方式绕过它。有没有办法连接到 Spock 的 属性 解析机制,或者告诉 Spock 使用我重写的方法?

是的,您可以使用 "Expando" 样式,其中 属性 不应在规范 class 上定义,而是存储在地图中 (storage) 并且由 setPropertygetProperty 方法操作:

class MetaprogrammingSpec extends Specification {
    def storage = [:]

    @Override
    def getProperty(String name) {
        def value = storage[name]
        println "$name == $value"
        return value
    }

    @Override
    void setProperty(String name, value) {
        storage[name] = value
    }

    def test() {
        when:
        foo = 'bar'

        then:
        foo
        println foo
    }
}

那么结果就是:

评论后更新:不初始化foo属性时也会调用getProperty()方法。当您以这种方式更改测试时:

def test() {
    expect:
    foo
    println foo
}

结果如预期 - getProperty() 被调用但测试失败,因为 foonull

事实证明,将 属性 移动到父级 class 足以使其通过 getProperty() 拦截器,即使父级是另一个 Specification class.

class BaseSpec extends Specification {
    def foo = 'foo'
}

class MainSpec extends BaseSpec {
    @Override
    def getProperty(String name) {
        def value = super.getProperty(name)
        println "$name == $value"
        return value
    }

    def test() {
        expect:
        foo
        println foo
    }
}