spock - 看到 Spock 的奇怪行为和从 AWS API Gateway SDK 生成的代码
问题描述
在模拟通过 AWS API Gateway (SDK) 生成的对象时,我遇到了一个异常行为,这很可能是一个 Spock 错误。
例如给定以下测试用例:
def "testing api gateway"() {
given:
def sdk = Mock(MyAWSSDK.class)
sdk.lookupByField("xyz") >> "result"
when:
def myClass = newClass(sdk)
myClass.foo()
then:
1 * sdk.lookupByField(_)
}
在我的例子中,当测试用例中出现“1 * sdk.lookupByField( )”时,我得到空指针异常。如果我将其取出并将 then: 条件替换为“true”。测试用例运行没有问题。我还可以在 when: 阶段“sdk.lookupByField(null)”中添加一个附加行,并将“1 * sdk.lookupByField( )”添加回“then:”阶段。它似乎工作。然而,这并不理想。
这是 Spock 的一种奇怪行为,似乎与 AWS API Gateway 生成的代码有关。
我尝试了 JDK 版本 1.8.0_202 和 11.0.1
Maven依赖:
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.9.9</version>
</dependency>
我计划用 Spock 创建一个错误,但想联系社区,看看是否可以复制。如果那里有任何接受者,将不胜感激。
解决方案
首先,您正在展示一个测试,但没有正在测试的课程。下次您在 SO 上提出问题时,请提供完整的MCVE,因为为了重现您的问题,我必须自己创建它,即使这本来是您的工作。谢谢你。
没有 Spock 错误,但您的测试代码中有两个错误:
- 应该怎么
newClass(sdk)
做?我假设您想在那里创建一个MyClass
对象,并且可能更想编写def myClass = new MyClass(sdk)
. - 正如Spock 手册所解释的,如果你想结合 mocking 和 stubbing,它们必须发生在同一个交互中。你的假设,你可以先写
sdk.lookupByField("xyz") >> "result"
,然后再写,1 * sdk.lookupByField(_)
以便先设置存根返回值,然后再设置预期调用的数量,因此是错误的。您必须在同一个地方定义两者。否则,模拟方法将返回null
(默认值),而不是"result"
,因为第一个语句被第二个语句覆盖。
您的解决方案如下所示:
package de.scrum_master.stackoverflow.q54636103
class MyAWSSDK {
String lookupByField(String s) {
"real result"
}
}
package de.scrum_master.stackoverflow.q54636103
class MyClass {
MyAWSSDK myAWSSDK
MyClass(MyAWSSDK myAWSSDK) {
this.myAWSSDK = myAWSSDK
}
String foo(String s) {
myAWSSDK.lookupByField("xyz")
}
}
package de.scrum_master.stackoverflow.q54636103
import spock.lang.Specification
class ApiGatewayTest extends Specification {
def "testing api gateway the wrong way"() {
given:
def sdk = Mock(MyAWSSDK)
sdk.lookupByField("xyz") >> "mock result"
when:
def myClass = new MyClass(sdk)
def result = myClass.foo()
then:
1 * sdk.lookupByField(_)
result == "mock result" // uh-oh!
}
def "testing api gateway the right way"() {
given:
def sdk = Mock(MyAWSSDK)
when:
def myClass = new MyClass(sdk)
def result = myClass.foo()
then:
1 * sdk.lookupByField("xyz") >> "mock result"
result == "mock result" // yeah!
}
}
第一个特征方法会失败如下,第二个会通过:
Condition not satisfied:
result == "mock result" // uh-oh!
| |
null false
推荐阅读
- python - 如何使用 python 和 pandas 通过逐行读取来创建列表?
- java - 将函数和参数传递给另一个函数
- sql - 在更多行和列上创建 sql pivot
- css - 用于描边动画的具有多个原点的 SVG 圆
- bixby - 在向用户显示输入视图时,如何让用户提供 NL 输入?
- javascript - 7 位数字的正则表达式,中间有可选的特殊字符
- symbolic-math - diff 函数不适用于希腊字母
- node.js - 有没有办法在后端( node js )上使用 webpack 构建 node_modules ?
- sql-server - 是否总是可以在不使用 sql 中的临时表的情况下使用 while 循环和变量将多个空间选择转换为单个查询?
- flutter - ListView 和 ListView.builder 有什么区别,我们可以使用 Listview.builder 创建、验证和提交表单吗?