在Groovy/Spock中,不会执行断言调用方法

在Groovy/Spock中,不会执行断言调用方法,groovy,spock,Groovy,Spock,在使用Spock的Groovy单元测试中,以下任务非常常见: assert myResult==calculateExpectedResult()(带或不带assert关键字。) groovy断言输出了大量关于这里发生了什么以及我的断言失败的原因的信息。但是,当比较的对象非常复杂和深入时,获取未通过测试的具体属性可能会很棘手 为此,我找到了一个很好的方法来比较对象并产生精确的差异。我创造了一个特点来做到这一点: trait DiffTrait { Javers javers = Javer

在使用Spock的Groovy单元测试中,以下任务非常常见:

assert myResult==calculateExpectedResult()
(带或不带
assert
关键字。)

groovy断言输出了大量关于这里发生了什么以及我的断言失败的原因的信息。但是,当比较的对象非常复杂和深入时,获取未通过测试的具体属性可能会很棘手

为此,我找到了一个很好的方法来比较对象并产生精确的差异。我创造了一个特点来做到这一点:

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()
这样我就得到了一份打印得很好的差异列表

但这有点冗长,因为我必须指定两次值

所以我改变了这样的特点:

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()
我们的想法是这样使用它:

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异常。如果我调试此代码,则不会调用
预期的
/
结果
方法

如果我像这样重写代码

def result = result(callTheSystemToProduceTheRealResult())
def expected = expected(calculateExpectedResult())
assert myResult == expected, diff()
一切正常。正确调用方法并设置属性

我的问题是:为什么我不能在assert语句中调用这些方法?从Groovy/Spock的角度来看,这两个代码片段有什么不同


下面是一个包含所有代码的运行示例。

这很容易解释。断言消息在断言本身之前进行计算。以下代码工作正常,但它显示静态
diff
消息:

import org.javers.core.Javers
import org.javers.core.JaversBuilder
import org.javers.core.diff.Diff
import org.javers.core.diff.changetype.ValueChange
import spock.lang.Specification

class LolSpec extends Specification implements DiffTrait {

    def 'lol'() {
        expect:
        def whatIGot = new Lol(l: 'a')
        def whatIExpected = new Lol(l: 'b')
        assert result(whatIGot) == expected(whatIExpected), 'diff'
    }

}

trait DiffTrait {

    Javers javers = JaversBuilder.javers().build()

    def result
    def expected

    String diff() {
        diff(result, 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
    }

    def result(result) {
        this.result = result
        return result
    }

    def expected(expected) {
        this.expected = expected
        return expected
    }
}

class Lol {
    String l
}
您需要传递两次参数或更改实现,例如:

import groovy.transform.EqualsAndHashCode
import org.javers.core.Javers
import org.javers.core.JaversBuilder
import org.javers.core.diff.changetype.ValueChange
import spock.lang.Specification

class LolSpec extends Specification {

    def 'lol'() {
        expect:
        def whatIGot = new Lol(l: 'a')
        def whatIExpected = new Lol(l: 'b')
        def diff = new Diff(result: whatIGot, expected: whatIExpected)
        assert diff.check(), diff.message()
    }

}

class Diff {

    Javers javers = JaversBuilder.javers().build()

    def result
    def expected

    String message() {
        def 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
    }

    boolean check() {
        result.equals(expected)
    }

}

@EqualsAndHashCode
class Lol {
    String l
}