我有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
}
}
试试这样的方法
given: 'a math with a calculator that always returns 100'
def calc = Stub(CalcIntf) {
bMethod(_,_,_) >> 100
}
def math = new Math(calc)
when: 'the math is asked to calculate something'
def result = math.m2()
then: 'it returns 100'
result == 100
需要注意的地方。
推送到stub上的返回值应该是返回的内容,而不是闭包。
你必须在数学中通过构造函数或其他方式设置存根计算。
你在数学上调用的方法不需要参数。
我把你编辑之前的原问题的代码抄了下来,至少能让你的代码更合理一些。请你 从来没有 在没有运行它并检查它是否能重现问题的情况下发布示例代码。伪代码对任何人都没有帮助,对试图回答你的问题的社区没有帮助,对你自己也没有帮助,因为你只会引起疯狂的猜测,而不是得到正确的答案。在生活中,这个原则也同样适用于编程:垃圾进,垃圾出。
所以我先做了 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
...
失败的原因是你没有在任何地方注入你的mock,但是... ... Math
使用硬编码的 Calc
例子 Calc calc = new Calc()
.
所以我们需要一种方法来注入mock,例如通过构造函数或setter。你也应该把字段类型从 Calc
到 CalcIntf
因为否则无法注入接口mock。如果你的代码中不使用接口,而是针对具体的子类进行编码,为什么要创建接口呢?
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
,这意味着实现mock的动态代理不能覆盖它,从而不能存根。但这与你在代码中描述的情况完全不同。
看到了吗?你的示例代码是 一文不值 如果它不能重现问题,这就是为什么我在评论中告诉你要始终提供一个 MCVE 而不是一些随意的伪代码。一个专业的软件开发者没有理由这么懒惰。如果有人报告你的代码有bug,你也想知道如何重现。对不起,在这里教训你,但你需要有一些作为开发者的职业自豪感,学会如何提问。
所以为了重现你所报告的这样一个问题,我不得不做一个有根据的猜测,因为你的代码是没有用的。只要在上一个版本中修改以下内容就可以了。
int bMethod(int a, int b, int c)
→ final int bMethod(int a, int b, int c)
Mock(CalcIntf)
→ Mock(Calc)
两处现在测试结果是:一个合格,一个不合格的功能方法。
Condition not satisfied:
math.m2() == 456
| | |
| 6 false
...
希望对你有所帮助