Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Groovy 有没有办法防止Geb从void方法返回null?_Groovy_Spock_Geb - Fatal编程技术网

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

Groovy 有没有办法防止Geb从void方法返回null?,groovy,spock,geb,Groovy,Spock,Geb,在Spock规范中,expect:或then:块中的任何行都将被求值并断言为布尔值,除非它具有返回类型为void的签名 我注意到,对于从Navigator继承的任何类(例如Page或Module类),声明为void的方法都有一些奇怪的情况 假设我们有这样的例子: class NavigationSpec extends GebSpec { def 'Collections page has a right header'() { when: t

在Spock规范中,expect:then:块中的任何行都将被求值并断言为
布尔值
,除非它具有返回类型为
void
的签名

我注意到,对于从
Navigator
继承的任何类(例如
Page
Module
类),声明为
void
的方法都有一些奇怪的情况

假设我们有这样的例子:

class NavigationSpec extends GebSpec {

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

        when:
            to CollectionsPage

        then:
            hasHeaderText('Collections')
    }
}
hasHeaderText()
方法在
CollectionsPage
类中定义如下:

class CollectionsPage extends Page {

    static url = 'movies/collections'

    void hasHeaderText(String expectedText) {
        assert true
    }
}
我故意在那里断言
true
,这样它就永远不会失败。即使失败并出现错误:

Condition not satisfied:

hasHeaderText('Collections')
|
null
void
方法调用结果如何以及为什么被评估为
null

我知道如何“修复它”。将方法返回类型声明为
boolean
并返回
true
,就足够了。这很难看,因为必须添加以下所有不必要的断言
返回true

boolean hasHeaderText(String expectedText) {
    assert header.text() == expectedText
    return true
}
但这只会引起噪音。有没有办法防止Geb从
void
方法返回
null

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

boolean hasHeaderText(String expectedText) {
    header.text() == expectedText`
}

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

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

声明为
void
的所有方法返回
null

如果没有任何return语句,则返回方法中最后一个表达式的结果

你可以看看字节码。。。即使您声明了一个返回类型,实际上也不需要像Groovy那样返回任何东西,默认情况下,它将返回null:

// returns null
String callMe() { }

static void main(args) {
    def x = callMe()
    assert x == null
    println "OK!"
}
由于Spock将在
then
块中断言任何不是简单赋值的内容,因此需要避免在
then
块中执行布尔断言以外的任何操作。即使是赋值变量,尽管允许,也应该避免。。。保持测试的干净和清晰是很困难的,坚持这些指导原则从长远来看会对你有效,而不是对你不利

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

boolean hasHeaderText(String expectedText) {
    header.text() == expectedText
}
然后在
块中使用它:

then: 'The header has the expected text #expectedText'
hasHeaderText expectedText
如果你问我的话,看起来不错

编辑


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

@Renato在其回复的编辑部分是正确的-您对void方法的调用被Spock断言,因为这是一个动态调用,而Spock无法确定您正在调用void方法并急切地断言该调用。如果您将代码更改为:

class NavigationSpec extends GebSpec {

    def 'Collections page has a right header'() {
        when:
            CollectionsPage collectionsPage = to CollectionsPage

        then:
            collectionsPage.hasHeaderText('Collections')
    }

}

那么它就不会被断言。

谢谢你的回答。我知道你写的东西,特别是“编辑”笔记中的部分。实际上,void方法不应该在spock的then块中作为assert进行评估。Page的方法是以正常方式声明的,但这也是我的假设,Geb用它做了一些AST魔术,从而破坏了合同。在方法之外使用带有
expectedText
的布尔值远远不是我想要实现的。电源故障消息丢失(例如,考虑比较两个映射),每次使用该方法时都必须重复文本(DRY)。我认为这是一个GEB BUG谢谢你的答案。我很确定这是因为电话的动态性质。奇怪的是,如果直接在所属对象上调用,我没有发现它工作得很好。顺便问一下,我现在应该接受哪个答案@雷纳托是第一个,而你的给出了更多细节:)也许@Renato应该被接受,因为他的回答是第一个正确的回答你太谦虚了@Renato的回应只是对我自己的假设的一般性确认,即这是“某种动态魔法”,但既没有提供任何细节,也没有提供解决方案。因此,我接受你的。我希望他不介意……我没问题:)如果你在一年后仍在等待,我没问题,如果你接受@erdi-answer:)