为什么在 spock 中调用 with-method 时得到 "groovy.lang.MissingMethodException: No signature of method"?

Why a get "groovy.lang.MissingMethodException: No signature of method" when call with-method in spock?

我有一个集成测试。其中的一些代码:

Test1 {
        static closure1 = { Class1 resultState, Class1 originState ->
            with(resultState) {
                name == originState.name
                breed == originState.breed
                bornDate == originState.bornDate
            }
        }

        @Unroll
        def 'exercise #methodName'() {
            ...
            expected(resultState, originState)
            ...
            methodName  || expected
            'name1'     || closure1
        }
}

我得到一个 groovy.lang.MissingMethodException:没有方法签名:Test1$__clinit__closure10.with() 适用于参数类型:(Class1, Test1$__clinit__closure10$_closure12) 值:[ //值].

但是当我用方法而不是闭包重构我的代码时,一切都很好。

    Test1 {

            void method1(Class1 resultState, Class1 originState) {
                with(resultState) {
                    name == originState.name
                    breed == originState.breed
                    bornDate == originState.bornDate
                }
            }

            @Unroll
            def 'exercise #methodName'() {
                ...
                expected(resultState, originState)
                ...
                methodName  || expected
                'name1'     || closure1
             }


        }

但是为什么??在 closure-from 中,我在 with-block 中得到异常,而不是在 closure 调用中。 在我的其他测试形式中,闭包测试(但没有 with-block)工作正常。这里的闭包类型 - 闭包,在其他测试中 - 闭包,如果它很重要。

我的代码有什么问题??

一个问题是 withSpecification 上的一个方法,但是您在静态上下文中拥有它,所以此时没有 with 方法可以调用。 ..

另一个是这在规范方法之外,因此 a == b 行不会被断言,因为 spock dsl 不会接收它们...

一个解决方案是使它成为一个方法,并传入一个方法句柄,并断言你的值和 return 如果它们全部通过则为真:

private test1(resultState, originState) {
    with(resultState) {
        assert name == originState.name
        assert breed == originState.breed
        assert bornDate == originState.bornDate
    }
    true
}

@Unroll
def 'exercise #methodName'() {

    ...
    then:
    expected(resultState, originState)

    where:
    methodName  || expected
    'name1'     || this.&test1
}