有没有办法阻止Geb从void方法返回null?

top*_*opr 5 groovy spock geb

在Spock规范中,期望的任何行:或者然后: block被评估并断言为boolean,除非它具有返回类型的签名void.

我注意到void在继承的任何类Navigator(例如Page或Module类)上声明的方法有些奇怪.

假设我们有这样的例子:

class NavigationSpec extends GebSpec {

    def 'Collections page has a right header'() {

        when:
            to CollectionsPage

        then:
            hasHeaderText('Collections')
    }
}
Run Code Online (Sandbox Code Playgroud)

该hasHeaderText()方法在CollectionsPage类中定义如下:

class CollectionsPage extends Page {

    static url = 'movies/collections'

    void hasHeaderText(String expectedText) {
        assert true
    }
}
Run Code Online (Sandbox Code Playgroud)

故意我只是true在那里断言所以它永远不会失败.即使它失败并出现错误:

Condition not satisfied:

hasHeaderText('Collections')
|
null
Run Code Online (Sandbox Code Playgroud)

void方法调用结果的评估方式和原因是null什么?

我知道如何"修复它".将方法返回类型声明为return boolean并返回就足够了true.这是丑陋的,但是跟随所有断言,否则return true必须添加如下:

boolean hasHeaderText(String expectedText) {
    assert header.text() == expectedText
    return true
}
Run Code Online (Sandbox Code Playgroud)

这只会产生噪音.有没有办法防止Geb null从void方法返回?

当然,我知道这个具体案例可能是这样的:

boolean hasHeaderText(String expectedText) {
    header.text() == expectedText`
}
Run Code Online (Sandbox Code Playgroud)

这并不能解释丢失void返回类型的奇怪之处,更不用说我们用这种方法松散有意义的断言失败消息.

Ren*_*ato 4

每个方法都会返回一个值,这是 Groovy 语言的一部分。这允许在表达式中使用任何方法或作为 lambda。

所有声明为voidreturn 的方法null。

如果您没有显式地使用任何 return 语句,则将返回方法中最后一个表达式的结果。

您可以查看字节码...即使您声明了返回类型,您实际上也不需要返回任何内容,因为默认情况下,Groovy 将返回 null:

// returns null
String callMe() { }

static void main(args) {
    def x = callMe()
    assert x == null
    println "OK!"
}
Run Code Online (Sandbox Code Playgroud)

因为 Spock 会断言块中的任何then内容,这不是简单的赋值,所以您需要避免在块中执行除布尔断言之外的任何操作then。即使分配一个变量,虽然允许,但应该避免......保持测试干净和清晰是很困难的,并且遵守这些准则从长远来看确实对你有用,而不是对你不利。

因此,编写所需断言的正确方法是使方法返回布尔值:

boolean hasHeaderText(String expectedText) {
    header.text() == expectedText
}
Run Code Online (Sandbox Code Playgroud)

并在then块中使用它:

then: 'The header has the expected text #expectedText'
hasHeaderText expectedText
Run Code Online (Sandbox Code Playgroud)

如果你问我的话,看起来不错。

编辑

我注意到 Groovy/Spock 实际上不会断言正常void 方法的结果,即使在then块中...这里可能发生的情况是您没有正常的void 方法,您似乎正在调用动态方法CollectionsPage(我猜这就是 Geb 的魔力),这意味着 Spock AST Transformer 可能没有机会检查您正在调用的方法的签名,因此它正确地假设它必须断言结果。 . 至少看起来是这样。