Groovy 有没有办法防止Geb从void方法返回null?
在Spock规范中,expect:或then:块中的任何行都将被求值并断言为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
布尔值
,除非它具有返回类型为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:)