"Too few invocations"但是调用方法,并且所有内容都是使用GroovySpy或GroovyMock创建的



我有这样的类:

class A(B b, C c, D d, E e) {
protected void doSth() {
test();
}
protected void test() {
System.out.println("test");
}
}

我正在尝试测试是否调用doSth()方法,然后test()方法也被调用。方法的返回类型为 void,因此我无法测试这些方法的结果。

我的测试看起来像这样

def "test when doSth"() {
given: 'A class'
A aClass = GroovySpy(A, constructorArgs: [GroovyMock(B), GroovyMock(C), GroovyMock(D), GroovyMock(E)) as A
when:
A.doSth()
then:
1 * A.test()
}

但是这个测试不起作用。它给了我测试方法的"调用太少"错误。我真的很困惑,因为完全相同的示例但在构造函数中没有参数可以完美地工作。

首先,我不知道你的Java类有什么样的语法。我想它不是真正的Java,但也许像Kotlin这样的东西?我不知道,当涉及到JVM语言时,我只会说Java和Groovy。因此,让我像这样重新创建您的测试对象:

package de.scrum_master.stackoverflow.q56652868;
public class A {
private B b;
private C c;
private D d;
private E e;
public A(B b, C c, D d, E e) {
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}
protected void doSth() {
test();
}
protected void test() {
System.out.println("test");
}
public static class B {}
public static class C {}
public static class D {}
public static class E {}
}

我希望这没关系。

至于您的测试,我不确定测试此交互(doSth()调用的方法test())对您的应用程序是否真的至关重要,并且应该首先进行测试。我认为这种交互测试对于某些设计模式很重要,例如,您希望检查例如,当发生特定事件时,主题是否通知某些注册的观察者。测试类的内部连接,尤其是非公共方法,通常不会有太大的好处,并且可能导致过度规范和脆弱的测试,如果不是类的公共 API,而只是内部实现更改,则需要经常更新。

话虽如此,出于教育目的,现在让我回答您的问题。


测试中存在以下几个问题:

  • 语法错误。您缺少定义 Groovy 间谍的行中构造函数参数列表的结束]
  • 这不是一个真正的错误,但为什么要过度指定间谍的类型?而不是A aClass = GroovySpy(A, ...) as A你做3倍确保它真的是一个A.为什么不直接A aClass = GroovySpy(...)def aClass = GroovySpy(A, ...)?无需通过as AA转换为自身。
  • 不要使用Groovy模拟和间谍,普通的斯波克模拟和间谍就可以了。您不需要高级Groovy模拟功能,此外,对于本身未在Groovy中实现的目标类,这些功能无论如何都不起作用,如Spock手册中所述。他们只会表现得像普通的斯波克模拟。
  • 最后,但并非最不重要的是真正的错误:你写A.doSth()A.test(),就好像你在处理静态方法一样。为什么?你需要写aClass.doSth()aClass.test(),然后你的测试就会通过:
package de.scrum_master.stackoverflow.q56652868
import de.scrum_master.stackoverflow.q56652868.A.B
import de.scrum_master.stackoverflow.q56652868.A.C
import de.scrum_master.stackoverflow.q56652868.A.D
import de.scrum_master.stackoverflow.q56652868.A.E
import spock.lang.Specification
class ATest extends Specification {
def "test when doSth"() {
given: 'A class'
A aClass = Spy(constructorArgs: [Mock(B), Mock(C), Mock(D), Mock(E)])
when:
aClass.doSth()
then:
1 * aClass.test()
}
}

最新更新