如何获取声明为 class 的 Geb 模块实例?

How to get a Geb module instance with its declared class?

在 Geb 版本 0.10 之前,下面的示例代码工作得很好:

package whatever

import geb.Module
import geb.Page
import geb.spock.GebSpec

class ExampleSpec extends GebSpec {

    def 'MODULE - Y U NO HAVE THE RIGHT CLASS?'() {

        when:
            ExamplePage page = to ExamplePage

        then:
            verifySomething(page.theModule)
    }

    boolean verifySomething(ExampleModule module) {
        // ...
    }
}

class ExamplePage extends Page {

    static content = {
        theModule { module ExampleModule }
    }
}

class ExampleModule extends Module {

}

我想升级到最新的 0.13.1,但显然已经引入了突破性的(我会说是倒退的)变化,结果是:

groovy.lang.MissingMethodException: No signature of method: geb.navigator.NonEmptyNavigator.verifySomething() is applicable for argument types: (geb.content.TemplateDerivedPageContent) values: [whatever.ExamplePage -> theModule: whatever.ExampleModule]

我注意到从 0.11 版本开始也发生了同样的情况,但 class 不同,异常消息如下:

groovy.lang.MissingMethodException: No signature of method: geb.navigator.NonEmptyNavigator.verifySomething() is applicable for argument types: (geb.content.SimplePageContent) values: [theModule - SimplePageContent (owner: whatever.ExamplePage, args: [], value: null)]

为什么用给定的特定 class 声明的模块在运行时会丢失它?如何预防?

实现 Navigator 接口(包括从 Module 扩展的 类 )并从内容定义返回的对象被 TemplateDerivedPageContent 对象包裹,这些对象委托给底层对象但是还允许生成 meaningful path to the object for error reporting.

模块的包装在旧版本的 Geb 中工作,然后它被无意中删除,现在又回来了。尽管由于 TemplateDerivedPageContent 动态委托给基础对象,您仍然可以调用模块的所有方法,但在像您这样的情况下,您 运行 会遇到麻烦 - 当您想要强烈键入您的代码时使用模块。因此,我仍然不确定我们应该在这里牺牲什么 - 更好的错误报告或强类型的能力,并且这种包装可能会在 Geb 的未来版本中被删除。

幸运的是有一个解决方法 - 如果你想强类型代码使用模块然后使用 getter 而不是内容定义来声明它们。在你的情况下它将是:

class ExamplePage extends Page {

    ExampleModule getTheModule() {
        module ExampleModule
    }

}