Groovy Power Assert 空检查
Groovy Power Assert Null Check
我有一个 Groovy class 它接收一个参数给它的构造函数并用 Power Assert 语句检查它,如下所示:
public MyClass(Map args) {
assert args.firstArg
}
通常 args.firstArg
的值是我项目中另一个 Groovy class 的实例。当我使用这个 class 的真实实例时,断言通过了。但是,当我使用 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
只是 shorthand 进行空检查。
根据我在模拟 class 实例中观察到的情况,情况并非如此,我想知道是否有人可以帮助我理解其中的区别。
@hayfreed:其实我不喜欢猜测,所以请下次(或者这一次,以防我猜错)在 Whosebug 上提问时提供的不仅仅是一组不连贯的代码片段。理想情况下,提供一个 MCVE(请阅读!)。
让我们先创建一个 MCVE,好吗?
package de.scrum_master.Whosebug.q62543765
class OtherClass {}
package de.scrum_master.Whosebug.q62543765
class MyClass {
MyClass(Map args) {
assert args.firstArg
}
}
package de.scrum_master.Whosebug.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.Whosebug.q62543765
class OtherClass extends ArrayList<String> {}
特征方法 not 测试失败使用 mock:
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.Whosebug.q62543765.MyClassTest.do not use mock(MyClassTest.groovy:10)
Caused by: Assertion failed:
assert args.firstArg
| |
| []
['firstArg':[], 'secondArg':'foo']
at de.scrum_master.Whosebug.q62543765.MyClass.<init>(MyClass.groovy:5)
at de.scrum_master.Whosebug.q62543765.MyClassTest.do not use mock(MyClassTest.groovy:8)
所以你看到 Groovy truth 不仅仅是空检查。例如。如果集合为空,集合类型也会为断言产生 false
。
但是回到你的问题。模拟测试怎么会失败?我没有看到 OtherClass
的代码,我最好的猜测是 class 实现了一个 asBoolean
方法,正如手册中关于 Groovy 真相的部分所述:
package de.scrum_master.Whosebug.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.Whosebug.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.Whosebug.q62543765.MyClass.<init>(MyClass.groovy:5)
at de.scrum_master.Whosebug.q62543765.MyClassTest.use mock(MyClassTest.groovy:26)
你会如何解决这个问题?只需将 asBoolean
方法存根到 return true
:
def "use mock"() {
given:
def otherClass = Mock(OtherClass) {
asBoolean() >> true
}
when:
new MyClass([firstArg: otherClass, secondArg: "foo"])
then:
noExceptionThrown()
}
我有一个 Groovy class 它接收一个参数给它的构造函数并用 Power Assert 语句检查它,如下所示:
public MyClass(Map args) {
assert args.firstArg
}
通常 args.firstArg
的值是我项目中另一个 Groovy class 的实例。当我使用这个 class 的真实实例时,断言通过了。但是,当我使用 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
只是 shorthand 进行空检查。
根据我在模拟 class 实例中观察到的情况,情况并非如此,我想知道是否有人可以帮助我理解其中的区别。
@hayfreed:其实我不喜欢猜测,所以请下次(或者这一次,以防我猜错)在 Whosebug 上提问时提供的不仅仅是一组不连贯的代码片段。理想情况下,提供一个 MCVE(请阅读!)。
让我们先创建一个 MCVE,好吗?
package de.scrum_master.Whosebug.q62543765
class OtherClass {}
package de.scrum_master.Whosebug.q62543765
class MyClass {
MyClass(Map args) {
assert args.firstArg
}
}
package de.scrum_master.Whosebug.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.Whosebug.q62543765
class OtherClass extends ArrayList<String> {}
特征方法 not 测试失败使用 mock:
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.Whosebug.q62543765.MyClassTest.do not use mock(MyClassTest.groovy:10)
Caused by: Assertion failed:
assert args.firstArg
| |
| []
['firstArg':[], 'secondArg':'foo']
at de.scrum_master.Whosebug.q62543765.MyClass.<init>(MyClass.groovy:5)
at de.scrum_master.Whosebug.q62543765.MyClassTest.do not use mock(MyClassTest.groovy:8)
所以你看到 Groovy truth 不仅仅是空检查。例如。如果集合为空,集合类型也会为断言产生 false
。
但是回到你的问题。模拟测试怎么会失败?我没有看到 OtherClass
的代码,我最好的猜测是 class 实现了一个 asBoolean
方法,正如手册中关于 Groovy 真相的部分所述:
package de.scrum_master.Whosebug.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.Whosebug.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.Whosebug.q62543765.MyClass.<init>(MyClass.groovy:5)
at de.scrum_master.Whosebug.q62543765.MyClassTest.use mock(MyClassTest.groovy:26)
你会如何解决这个问题?只需将 asBoolean
方法存根到 return true
:
def "use mock"() {
given:
def otherClass = Mock(OtherClass) {
asBoolean() >> true
}
when:
new MyClass([firstArg: otherClass, secondArg: "foo"])
then:
noExceptionThrown()
}