首页 文章

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

提问于
浏览
3

在使用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 回答

  • 3

    这很容易解释 . 在断言本身之前评估断言消息 . 以下代码完美无缺,但它显示静态 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
    }
    

相关问题