java - Spock模拟调用模拟类的真实方法
问题描述
我有 Spock 集成测试来测试我的 Java 应用程序。对于其中一种方法,调用将转到真正的方法“bMethod()”,而不是返回存根值。它适用于另一种方法'aMethd()',并且返回存根值并且不调用实际方法。这两种方法都在同一个类 Calc 中。有没有办法调查 Spock 在做什么以及为什么?
public interface CalcIntf {
public int aMethod(int a, int b);
public int bMethod(int a, int b, int c);
}
MyTestSpec extends Specification {
def "aMethod test"() {
given:
...
CalcIntf calcIntf = Mock(CalcIntf)
calcIntf.aMethod(_,_) >> { return 100; }
when:
//service call
then:
// asserts go here
}
def "bMethod test"() {
given:
...
CalcIntf calcIntf = Mock(CalcIntf)
calcIntf.bMethod(_,_,_) >> { return 100; }
when:
// service call
then:
// asserts go here
}
}
解决方案
具有最少修复的原始代码
所以首先我做了m1
并m2
返回int
而不是void
. 然后至少你可以检查结果。然后我还确保在没有参数的情况下正确调用这些方法,正如 Chris 已经提到的那样。所以现在代码看起来像这样:
package de.scrum_master.stackoverflow.q62269054
import spock.lang.Specification
class MyTestSpec extends Specification {
def "testing addition using aMethod"() {
given:
Math math = new Math()
CalcIntf calcIntf = Mock(CalcIntf)
calcIntf.aMethod(_, _) >> { return 123 }
expect:
math.m1() == 123
}
def "testing addition using bMethod"() {
given:
Math math = new Math()
CalcIntf calcIntf = Mock(CalcIntf)
calcIntf.bMethod(_, _, _) >> { return 456 }
expect:
math.m2() == 456
}
interface CalcIntf {
int aMethod(int a, int b)
int bMethod(int a, int b, int c)
}
static class Calc implements CalcIntf {
int aMethod(int a, int b) {
return a + b
}
int bMethod(int a, int b, int c) {
return a + b + c
}
}
static class Math {
Calc calc = new Calc()
int m1() {
calc.aMethod(1, 2)
}
int m2() {
calc.bMethod(1, 2, 3)
}
}
}
当然,测试失败:
Condition not satisfied:
math.m1() == 123
| | |
| 3 false
...
Condition not satisfied:
math.m2() == 456
| | |
| 6 false
...
失败的原因是你没有在任何地方注入你的模拟,而是Math
通过.Calc
Calc calc = new Calc()
使测试通过
所以我们需要一种注入模拟的方法,例如通过构造函数或设置器。您还应该将字段类型从更改为Calc
,CalcIntf
否则无法注入接口模拟。如果您不在代码中使用接口而是针对具体子类编写代码,为什么还要创建接口?
package de.scrum_master.stackoverflow.q62269054
import spock.lang.Specification
class MyTestSpec extends Specification {
def "testing addition using aMethod"() {
given:
CalcIntf calcIntf = Mock(CalcIntf)
calcIntf.aMethod(_, _) >> { return 123 }
Math math = new Math(calcIntf)
expect:
math.m1() == 123
}
def "testing addition using bMethod"() {
given:
CalcIntf calcIntf = Mock(CalcIntf)
calcIntf.bMethod(_, _, _) >> { return 456 }
Math math = new Math(calcIntf)
expect:
math.m2() == 456
}
interface CalcIntf {
int aMethod(int a, int b)
int bMethod(int a, int b, int c)
}
static class Calc implements CalcIntf {
int aMethod(int a, int b) {
return a + b
}
int bMethod(int a, int b, int c) {
return a + b + c
}
}
static class Math {
CalcIntf calcIntf
Math(CalcIntf calcIntf) {
this.calcIntf = calcIntf
}
int m1() {
calcIntf.aMethod(1, 2)
}
int m2() {
calcIntf.bMethod(1, 2, 3)
}
}
}
您描述的测试行为
所以现在测试通过了,但它们不会重现您描述的行为:
对于其中一种方法,调用将转到真正的方法“bMethod()”,而不是返回存根值。
我可以想象会发生这种情况的一个原因:您要存根的方法是final
,这意味着实现模拟的动态代理不能覆盖它,因此不能存根它。但这与您在代码中描述的情况完全不同。
看?如果您的示例代码不能重现问题,那么它就完全没用,这就是为什么在我的评论中我告诉您始终提供MCVE而不是一些随机的伪代码。如果有人报告了您的代码中的错误,您还想知道如何重现它。
因此,为了重现您报告的问题,我必须做出有根据的猜测,因为您的代码没有帮助。只需在以前的版本中更改以下内容:
int bMethod(int a, int b, int c)
→final int bMethod(int a, int b, int c)
Mock(CalcIntf)
→Mock(Calc)
在 2 个地方
现在测试结果是:一种通过,一种失败的特征方法:
Condition not satisfied:
math.m2() == 456
| | |
| 6 false
...
推荐阅读
- idris - 尝试定义新的 Python (如 pow 运算符)时出现编译错误
- assembly - 调用者 - 调用者在程序集中保存了寄存器和调用约定?
- html - 防止可滚动 Flex Div 中的项目改变页面布局
- javascript - 我们如何通过原生 JS 添加 loading="lazy"?
- react-native - react-native-dialogflow 中的 result.queryResult.fulfillmentMessages[0].text.text[0] 是什么?
- node.js - 有没有办法根据 node_modules 文件夹确定主机操作系统和节点版本?
- c# - 使用 Azure 函数的简单发布请求
- python - 将python函数结果存储在不同的csv中?
- javascript - 传单控件没有响应点击
- javascript - 如何从 React on change 中获取 key 而不是 value?