在使用Spock的Groovy单元测试中,以下任务非常常见:
assert myResult == calculateExpectedResult()
(带或不带 assert
关键字 . )
groovy断言打印出大量关于这里发生的事情的信息,以及为什么我的断言失败了 . 但是当比较的对象非常复杂和深度时,它可能会变得棘手,所以获得未通过测试的具体属性 .
为此,我发现Javers Framework做了一个很好的工作比较对象和产生一个精确的差异 . 我创建了一个特性来做到这一点:
trait DiffTrait {
Javers javers = JaversBuilder.javers().build()
String diff(result, expected) {
Diff diff = javers.compare(result, expected);
def valueChanges = diff.getChangesByType(ValueChange)
String message = ""
valueChanges.each { message += "\n$it.propertyName = $it.left instead of expected: $it.right" }
return message
}
}
现在我可以在我的单元测试中使用它,如下所示:
def expected = calculateExpectedResult()
assert myResult == expected, diff(myResult, expected)
通过这种方式,我得到了一个很好的打印差异列表 .
但这有点冗长,因为我必须指定两次值 .
所以我改变了这样的特征:
trait DiffTrait {
Javers javers = JaversBuilder.javers().build()
def result
def expected
String diff(result, expected) {
Diff diff = javers.compare(result, expected);
def valueChanges = diff.getChangesByType(ValueChange)
String message = ""
valueChanges.each { message += "\n$it.propertyName = $it.left instead of expected: $it.right" }
return message
}
String diff() {
diff(result, expected)
}
def result(result) {
this.result = result
return result
}
def expected(expected) {
this.expected = expected
return expected
}
}
想法是这样使用它:
def result = callTheSystemToProduceTheRealResult()
def expected = calculateExpectedResult()
assert result(myResult) == expected(expected), diff()
但令人惊讶的是,这不起作用!这两个属性为null,diff方法因NotNull-Exception而失败 . 如果我调试此代码,则永远不会调用 expected
/ result
方法!
如果我像这样重写代码
def result = result(callTheSystemToProduceTheRealResult())
def expected = expected(calculateExpectedResult())
assert myResult == expected, diff()
一切都按预期工作 . 正确调用方法并设置属性 .
我的问题是:为什么我不能在assert语句中调用这些方法?这两个代码片段的Groovy / Spock视角有什么区别?
这是一个包含所有代码作为运行示例的gist .
1 回答
这很容易解释 . 在断言本身之前评估断言消息 . 以下代码完美无缺,但它显示静态
diff
消息:您需要传递两次参数或更改实现,例如: