为什么 Spock 的交互不适用于其他 class 构建的 Mock

Why Spock's Interactions doesn't work for Mock that built by other class

我正在尝试 assemble 将所有 Mock 构建方法合而为一 class。 但是当我使用通过在其他 groovy class 上构建方法构建的 Mock 对象时。 Mock 的存根似乎工作正常,但交互检查不起作用。 好吧...我该如何实现?

MockTestingSpec.groovy

class MockTestingSpec extends Specification{

    def "use mock from other class"(){
        setup:"construct mock builder"
        def bldr = new MockBuilder()

        when:"build mock by MockBuilder"
        def mockObj = bldr.buildMock()

        and:"build mock by private method of this class"
        def builtAtThisClass = buildMock()

        then:"check stubbing are working. these conditions were satisfied"
        mockObj.getKey().equals("keyyyy")
        mockObj.getValue() == 12345
        builtAtThisClass.getKey().equals("keyyyy")
        builtAtThisClass.getValue() == 12345

        when:"put a mock to private method"
        callMockGetter(builtAtThisClass)

        then:"call each getter, these conditions were also satisfied"
        1 * builtAtThisClass.getKey()
        1 * builtAtThisClass.getValue()

        when:"puta a mock that built by builder"
        callMockGetter(mockObj)

        then:"these conditions were NOT satisfied... why?"
        1 * mockObj.getKey()
        1 * mockObj.getValue()
    }
    // completely same method on MockBuilder.
    private buildMock(String key = "keyyyy",Integer value = 12345){
        TestObject obj = Mock()
        obj.getKey() >> key
        obj.getValue() >> value
        return obj
    }

    private callMockGetter(TestObject obj){
        obj.getKey()
        obj.getValue()
    }
}

MockBuilder.groovy

class MockBuilder extends Specification{

    public buildMock(String key = "keyyyy",Integer value = 12345){
        TestObject obj = Mock()
        obj.getKey() >> key
        obj.getValue() >> value
        return obj
    }

    public static class TestObject{
        private String key
        public String getKey(){
            return key
        }
        private Integer value
        public Integer getValue(){
            return value
        }
    }
}

改为将模拟创建移至超类。这样您就可以在多个规范中重复使用复杂的模拟创建。

abstract class MockCreatingSpec extends Specification {
    createComplexMockInSuperClass() {
        return Mock()
    }
}
class MockTestingSpec extends MockCreatingSpec {
    def "use mock from superclass"() {
        given:
        def mock = createComplexMockInSuperClass()
        ...
    }
}