【问题标题】:Groovy Power Assert Null CheckGroovy Power Assert Null 检查
【发布时间】:2020-06-23 21:06:48
【问题描述】:

我有一个 Groovy 类,它接收其构造函数的参数并使用 Power Assert 语句检查它,如下所示:

public MyClass(Map args) {
    assert args.firstArg
}

通常args.firstArg 的值是我项目中另一个 Groovy 类的实例。当我使用此类的真实实例时,断言通过了。但是,当我使用 Spock Mocking 框架传入该方法的模拟实例时,断言失败:

Assertion failed: 

assert args.firstArg
       |    |
       |    Mock for type 'OtherClass' named 'mockOtherClass'
       ['firstArg':Mock for type 'OtherClass' named 'mockOtherClass']

但是,当我将代码更改为

assert args.firstArg != null

那么我的代码就可以工作了。

到目前为止,我还天真地认为

assert args.firstArg

只是做空检查的简写。

根据我观察到的传递模拟类实例的情况,情况并非如此,我想知道是否有人可以帮助我理解其中的区别。

【问题讨论】:

  • 你是如何创建模拟的?

标签: groovy mocking spock


【解决方案1】:

@hayfreed:其实我不喜欢推测,所以下次(或者这次,以防我猜错了)在 StackOverflow 上提问时,请提供的不仅仅是一组不连贯的代码 sn-ps。理想情况下,提供MCVE(请阅读!)。

让我们先创建一个 MCVE,好吗?

package de.scrum_master.stackoverflow.q62543765

class OtherClass {}
package de.scrum_master.stackoverflow.q62543765

class MyClass {
  MyClass(Map args) {
    assert args.firstArg
  }
}
package de.scrum_master.stackoverflow.q62543765

import spock.lang.Specification

class MyClassTest extends Specification {
  def "do not use mock"() {
    when:
    new MyClass([firstArg: new OtherClass(), secondArg: "foo"])
    then:
    noExceptionThrown()

    when:
    new MyClass([firstArg: null, secondArg: "foo"])
    then:
    thrown AssertionError

    when:
    new MyClass([secondArg: "foo"])
    then:
    thrown AssertionError
  }

  def "use mock"() {
    when:
    new MyClass([firstArg: Mock(OtherClass), secondArg: "foo"])
    then:
    noExceptionThrown()
  }
}

此测试通过。但是如果我们将OtherClass 改为集合类型呢?

package de.scrum_master.stackoverflow.q62543765

class OtherClass extends ArrayList<String> {}

使用 mock 的特征方法 not 测试失败:

Expected no exception to be thrown, but got 'org.codehaus.groovy.runtime.powerassert.PowerAssertionError'

    at spock.lang.Specification.noExceptionThrown(Specification.java:118)
    at de.scrum_master.stackoverflow.q62543765.MyClassTest.do not use mock(MyClassTest.groovy:10)
Caused by: Assertion failed: 

assert args.firstArg
       |    |
       |    []
       ['firstArg':[], 'secondArg':'foo']

    at de.scrum_master.stackoverflow.q62543765.MyClass.<init>(MyClass.groovy:5)
    at de.scrum_master.stackoverflow.q62543765.MyClassTest.do not use mock(MyClassTest.groovy:8)

所以你看到Groovy truth 不仅仅是一个空检查。例如。如果集合为空,集合类型也会为断言产生 false

但回到你的问题。模拟测试怎么会失败?我最好的猜测是,没有看到您的 OtherClass 的代码,该类实现了一个 asBoolean 方法,如手册中有关 Groovy 真相的部分所述:

package de.scrum_master.stackoverflow.q62543765

class OtherClass {
  boolean asBoolean(){
    true
  }
}

现在测试失败看起来很像你的:

Expected no exception to be thrown, but got 'org.codehaus.groovy.runtime.powerassert.PowerAssertionError'

    at spock.lang.Specification.noExceptionThrown(Specification.java:118)
    at de.scrum_master.stackoverflow.q62543765.MyClassTest.use mock(MyClassTest.groovy:28)
Caused by: Assertion failed: 

assert args.firstArg
       |    |
       |    Mock for type 'OtherClass'
       ['firstArg':Mock for type 'OtherClass', 'secondArg':'foo']

    at de.scrum_master.stackoverflow.q62543765.MyClass.<init>(MyClass.groovy:5)
    at de.scrum_master.stackoverflow.q62543765.MyClassTest.use mock(MyClassTest.groovy:26)

你会如何解决这个问题?只需存根asBoolean 方法即可返回true

  def "use mock"() {
    given:
    def otherClass = Mock(OtherClass) {
      asBoolean() >> true
    }
    when:
    new MyClass([firstArg: otherClass, secondArg: "foo"])
    then:
    noExceptionThrown()
  }

【讨论】:

  • 感谢您的回复,很抱歉您发现我的问题语无伦次。我认为您为此进行的测试非常好,我将尝试复制类似的东西。在这种情况下,OtherClass 没有实现 asBoolean() 方法,所以我认为不是这样。但我发现有关 Groovy 真理的文档也非常有帮助。我将把答案标记为已接受,因为这里有很多细节可能会对遇到类似问题的人有所帮助。
猜你喜欢
  • 2016-06-26
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-27
  • 2014-09-22
  • 1970-01-01
相关资源
最近更新 更多