我有一个模拟方法可以接受抽象类型的所有子项。在测试中,这个方法可能被不同的子项多次调用,我想检查它是否被特定类型调用一次这样:
1*mockObject.method(_) {SpecificType ct->
//check the ct's field value
}
问题是闭包始终捕获第一次调用,原因是:
mockObjectt.method(_)
无法区分不同的子类型,因此它匹配所有调用,然后我尝试了另外一种方式:
1*mockObject.method({it instanceof SpecificType}) {SpecificType ct->
//check the ct's field value
}
但这种方式的问题是:
{SpecificType ct->
//Here,any check will return true,
//I think the checkings in here are ignored
}
总是被忽略(我想我在这里误用了groovy')
所以问题是:
Is there elegant way to capture the invocation by specific child type with specific values and ignore others?
答案 0 :(得分:2)
怎么样:1*mockObject.method({it instanceof SpecificType && it.field == fieldValue })
?
答案 1 :(得分:1)
看看这个示例代码:
import spock.lang.Specification
class SimpleTestSpec extends Specification {
private static class A { }
private static class B extends A { }
private static class C extends B { }
private static class D extends A { }
private static class TestClass {
String foo(A value) {
return "A: ${value}"
}
String foo(B value) {
return "B: ${value}"
}
String foo(C value) {
return "C: ${value}"
}
String foo(D value) {
return "D: ${value}"
}
}
private static class ComponentClass {
private final TestClass testClass
ComponentClass(TestClass testClass) {
this.testClass = testClass
}
String foo(A value) {
return testClass.foo(value)
}
}
TestClass testClassMock = Mock(TestClass)
ComponentClass componentClass = new ComponentClass(testClassMock)
def setup() {
testClassMock.foo(_ as D) >> "DDD"
testClassMock.foo(_ as C) >> "CCC"
testClassMock.foo(_ as B) >> "BBB"
testClassMock.foo(_ as A) >> "AAA"
}
def "should use mocked DDD result"() {
when:
String result = testClassMock.foo(new D())
then:
result == "DDD"
}
def "should use mocked CCC result"() {
when:
String result = testClassMock.foo(new C())
then:
result == "CCC"
}
def "should use mocked BBB result"() {
when:
String result = testClassMock.foo(new B())
then:
result == "BBB"
}
def "should use mocked AAA result"() {
when:
String result = testClassMock.foo(new A())
then:
result == "AAA"
}
def "should record invocation based on dynamic type"() {
when:
componentClass.foo(new C())
then:
1 * testClassMock.foo(_ as C)
}
def "should return result associated with mocked invocation in runtime"() {
when:
String result = componentClass.foo(new D())
then:
result == "DDD"
}
}
Gist文件:https://gist.github.com/wololock/c59151b67d4c9b0c0c8e
您可以使用as
强制转换运算符指定参数的预期类型。但是有一个棘手的部分 - 您需要按特定顺序存根类行为:从最具体到最一般。尝试混合setup()
中的顺序,然后您将看到测试将开始失败。
您还可以使用Groovy的动态方法调用 - 注意ComponentClass
如何使用之前存在预期行为的injectest TestClass
实例。即使通过最常规的类型方法进行外部调用,您也可以计算与特定类型相关的调用次数。
我希望它可以帮助您解决问题。最好!