In Groovy/Spock assert call methods are not executed

Viewed 1416

In Groovy Unit Test with Spock the following task is quite common:

assert myResult == calculateExpectedResult() (With or without the assert keyword.)

The groovy assert prints out lots of infomation on what is going on here and why my assertion failed. But when the compared objects are very complex and deep it can be tricky go get the concrete property that failed the test.

For this I found the Javers Framework that does an excellent Job comparing the objects and producing an exact diff. I created a trait to do this:

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
  }
}

Now I can use it in my Unit Tests like this:

def expected = calculateExpectedResult()
assert myResult == expected, diff(myResult, expected)

This way I get a nicely printed list of differences.

But this is kind of verbose because I have to specify the values two times.

So I have changed the trait like this:

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
  }
}

The idea was to use it like this:

def result = callTheSystemToProduceTheRealResult()
def expected = calculateExpectedResult()
assert result(myResult) == expected(expected), diff()

But surprisingly this does not work! The two attributes are null and the diff Method fails with a NotNull-Exception. If I debug this code the expected/result methods are never called!

If I rewrite the code like this

def result = result(callTheSystemToProduceTheRealResult())
def expected = expected(calculateExpectedResult())
assert myResult == expected, diff()

everything works as expected. The methods get called correctly and the attributes are set.

My question is: Why can't I call these methods in the assert statement? What is the difference from the Groovy/Spock perspective of these two code fragements?

Here is a gist containing all the code as running example.

1 Answers
Related