"Too few invocations" 但是方法被调用并且一切都是使用 GroovySpy 或 GroovyMock 创建的
"Too few invocations" but method is invoked and everything is created using GroovySpy or GroovyMock
我有 class 这样的:
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()
}
但是这个测试不起作用。它给了我 "Too few invocations" 测试方法错误。我真的很困惑,因为完全相同的例子,但在构造函数中没有参数,效果很好。
首先,我不知道你的Javaclass是什么语法。我想这不是真的 Java 但也许像 Kotlin?我不知道,关于 JVM 语言,我只会说 Java 和 Groovy。所以让我像这样重新创建您的测试对象:
package de.scrum_master.Whosebug.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()
)是否对您的应用程序真的很重要,应该首先进行测试。我认为这种交互测试对于某些设计模式很重要,例如想检查是否例如当特定事件发生时,主题会通知某些已注册的观察者。测试 class 的内部连接,尤其是 non-public 方法,通常不会有多大用处,并且会导致 over-specification 和脆弱的测试,如果不是 [=53],则需要经常更新=] 的 public API 但只是内部实现发生了变化。
话虽如此,出于教育目的,现在让我回答你的问题。
你的测试有几处错误:
- 语法错误。您在定义 Groovy 间谍的行中缺少构造函数参数列表的结束
]
。
- 不是真正的错误,但为什么 over-specify 你的间谍类型?而不是
A aClass = GroovySpy(A, ...) as A
,你 3 倍确定它确实是一个 A
。为什么不只是 A aClass = GroovySpy(...)
或者 def aClass = GroovySpy(A, ...)
?无需通过 as A
. 也将 A
转换为自身
- 不要使用 Groovy 模拟和间谍,正常的 Spock 模拟和间谍就可以了。您不需要高级 Groovy 模拟功能,此外,对于目标 classes,它们本身并未在 Groovy 中实现,这些功能无论如何都不起作用,如 Spock 手册中所述。他们的行为就像正常的 Spock 模拟一样。
- 最后但并非最不重要的是真正的错误:你写
A.doSth()
和 A.test()
就好像你在处理静态方法一样。为什么?你需要写 aClass.doSth()
和 aClass.test()
,那么你的测试将通过:
package de.scrum_master.Whosebug.q56652868
import de.scrum_master.Whosebug.q56652868.A.B
import de.scrum_master.Whosebug.q56652868.A.C
import de.scrum_master.Whosebug.q56652868.A.D
import de.scrum_master.Whosebug.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()
}
}
我有 class 这样的:
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()
}
但是这个测试不起作用。它给了我 "Too few invocations" 测试方法错误。我真的很困惑,因为完全相同的例子,但在构造函数中没有参数,效果很好。
首先,我不知道你的Javaclass是什么语法。我想这不是真的 Java 但也许像 Kotlin?我不知道,关于 JVM 语言,我只会说 Java 和 Groovy。所以让我像这样重新创建您的测试对象:
package de.scrum_master.Whosebug.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()
)是否对您的应用程序真的很重要,应该首先进行测试。我认为这种交互测试对于某些设计模式很重要,例如想检查是否例如当特定事件发生时,主题会通知某些已注册的观察者。测试 class 的内部连接,尤其是 non-public 方法,通常不会有多大用处,并且会导致 over-specification 和脆弱的测试,如果不是 [=53],则需要经常更新=] 的 public API 但只是内部实现发生了变化。
话虽如此,出于教育目的,现在让我回答你的问题。
你的测试有几处错误:
- 语法错误。您在定义 Groovy 间谍的行中缺少构造函数参数列表的结束
]
。 - 不是真正的错误,但为什么 over-specify 你的间谍类型?而不是
A aClass = GroovySpy(A, ...) as A
,你 3 倍确定它确实是一个A
。为什么不只是A aClass = GroovySpy(...)
或者def aClass = GroovySpy(A, ...)
?无需通过as A
. 也将 - 不要使用 Groovy 模拟和间谍,正常的 Spock 模拟和间谍就可以了。您不需要高级 Groovy 模拟功能,此外,对于目标 classes,它们本身并未在 Groovy 中实现,这些功能无论如何都不起作用,如 Spock 手册中所述。他们的行为就像正常的 Spock 模拟一样。
- 最后但并非最不重要的是真正的错误:你写
A.doSth()
和A.test()
就好像你在处理静态方法一样。为什么?你需要写aClass.doSth()
和aClass.test()
,那么你的测试将通过:
A
转换为自身
package de.scrum_master.Whosebug.q56652868
import de.scrum_master.Whosebug.q56652868.A.B
import de.scrum_master.Whosebug.q56652868.A.C
import de.scrum_master.Whosebug.q56652868.A.D
import de.scrum_master.Whosebug.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()
}
}