在 Spock 中测试抽象或具体 class 的 属性 访问

Test for property access of an abstract or concrete class in Spock

当我使用 getter/setter 对模拟抽象或具体 class 然后访问 属性 时,相应的 getter/setter 永远不会被调用。但是,如果 Mock 是为接口创建的,这就可以正常工作。在下面的代码中,有 3 组,每组两个测试(一组测试 getter,另一组测试 setter),除了它们模拟的内容外,它们是相同的。第一套工作正常,因为他们正在界面上进行测试,但接下来的两套没有:

import spock.lang.Specification

interface Foo {
    public String getProp();
    public void setProp(String val);
}
abstract class FooBase implements Foo {
    public abstract String getProp();
    public abstract void setProp(String val);
}
class FooImpl extends FooBase {
    public String getProp() {
        println('Foo.getProp')
        return null
    }

    public void setProp(String val) {
        println('Foo.setProp')
    }
}
class TestPropertyAccess extends Specification {
    def 'test setter on interface'() {
        given:
            def foo = Mock(Foo)
        when:
            foo.prop = 'val'
        then:
            1 * foo.setProp(_)
    }

    def 'test getter on interface'() {
        given:
            def foo = Mock(Foo)
        when:
            foo.prop
        then:
            1 * foo.getProp()
    }

    def 'test setter on abstract'() {
        given:
            def foo = Mock(FooBase)
        when:
            foo.prop = 'val'
            //foo.setProp('val')
        then:
            1 * foo.setProp(_)
            //1 * foo.setProperty('prop', 'val')
    }

    def 'test getter on abstract'() {
        given:
            def foo = Mock(FooBase)
        when:
            foo.prop
            //foo.getProp()
        then:
            1 * foo.getProp()
            //1 * foo.getProperty('prop')
    }

    def 'test setter on concrete'() {
        given:
            def foo = Mock(FooImpl)
        when:
            foo.prop = 'val'
            //foo.setProp('val')
        then:
            1 * foo.setProp(_)
            //1 * foo.setProperty('prop', 'val')
    }

    def 'test getter on concrete'() {
        given:
            def foo = Mock(FooImpl)
        when:
            foo.prop
            //foo.getProp()
        then:
            1 * foo.getProp()
            //1 * foo.getProperty('prop')
    }
}

如果我用相应的 getter/setter 替换 属性 访问,或者如果我测试通用 getProperty/setProperty,我可以使失败的测试工作。

我是不是遗漏了什么或者这可能是 spock 错误?

抓得好!鉴于

这一事实,我会认为这是一个 Spock 错误
  • 当从常规 Groovy 程序调用时,如果您添加一个真正的 属性 并设置 setter 和getter明白了,
  • 测试在 Spock 1.3 和 2.0 预览版中表现不同(getter 测试有效,只有 setter 测试失败)。

可能在编译期间从 Spock DSL 生成实际代码的 AST 转换中出现了问题。

我刚刚为您打开了 bug ticket #1158


更新: 其实我只是注意到,如果应用程序 类 在 Java 中实现,它会按预期工作,但当然你不能使用方法 {get|set}Property 因为它们只定义在 GroovyObjects.


2020-10-28 更新:该问题已在 Spock master 中修复,并将成为 Spock 2.0 的一部分。请参阅问题 #1158。