如何在spock / groovy中窥探关闭或代理?
Spock有一个限制,您无法使用以下样式interaction testing模式:
setup:
subscriber.receive("message1") >> "ok"
when:
publisher.send("message1")
then:
1 * subscriber.receive("message1")
因为1 *
交互行会覆盖" ok"的存根返回。你必须把它们放在同一条线上:
1 * subscriber.receive("message1") >> "ok"
大多数情况下这是可以的,但是对于某些需要存在更复杂行为的情况,能够将存根行为和交互分开是非常好的。
我嘲笑/存根的所有内容都可以用Closure
表示,但我无法Spy
到Closure
工作(或Spy
到Proxy
到Closure
)。所以我有以下Closure-lite类:
#!groovy
import spock.lang.Specification
class C {
def c
C (Closure c) { this.c = c }
def call (Map args = null) { args? c?.call (args) : c?.call() }
def call (Map args = null, one) { args? c?.call (args, one) : c?.call (one) }
def call (Map args = null, one, two) { args? c?.call (args, one, two) : c?.call (one, two) }
// etc.
}
尽管它们分离了存根行为和交互,但仍允许以下测试通过:
class spyTest extends Specification {
void "should accept 0 args" () {
given:
def foo = Spy (C, constructorArgs:[{return "foo"}])
when:
def result = foo ()
then:
1 * foo()
result == "foo"
}
void "should accept 1 positional args, 0 named args" () {
given:
def foo = Spy (C, constructorArgs:[{ one -> ["foo", one]}])
when:
def result = foo (1)
then:
1 * foo(1)
result == ["foo", 1]
}
void "should accept 1 args, + 1 named args" () {
given:
def foo = Spy (C , constructorArgs:[{ args, one -> return ["foo", args, one]}])
when:
def result = foo (1, a:'a')
then:
1 * foo(1, a:'a')
result == ["foo", [a:'a'], 1]
}
void "should accept 2 args, + 0 named args" () {
given:
def foo = Spy (C , constructorArgs:[{ one, two -> return ["foo", one, two]}])
when:
def result = foo (1,2)
then:
1 * foo(1,2)
result == ["foo", 1, 2]
}
void "should accept 2 args, + 2 named args" () {
given:
def foo = Spy (C , constructorArgs:[{ args, one, two -> return ["foo", args, one, two]}])
when:
def result = foo (1,2, a:'a', b:'b')
then:
1 * foo(1,2,a:'a', b:'b')
result == ["foo", [a:'a', b:'b'], 1, 2]
}
}
这是可行的,如果有点笨重,但显然它更好更有活力"关闭"比我必须添加每个潜在数量的参数的类。
因此可能有更动态的解决方案(如何?),或者使用Spy
或GroovySpy
的事实是否禁止更加动态的间谍课?
答案 0 :(得分:0)
你能否详细说明一下,你所展示的一切都可以通过模拟轻松完成,而不需要间谍。
class MockTest extends Specification {
void "should accept 0 args" () {
given:
def foo = Mock (C)
when:
def result = foo ()
then:
1 * foo() >> 'foo'
result == "foo"
}
void "should accept 1 positional args, 0 named args" () {
given:
def foo = Mock (C)
when:
def result = foo (1)
then:
1 * foo(1) >> { args -> ["foo", args[0]]}
result == ["foo", 1]
}
void "should accept 1 args, + 1 named args" () {
given:
def foo = Mock (C)
when:
def result = foo (1, a:'a')
then:
1 * foo(1, a:'a') >> { args, one -> ["foo", args, one]}
result == ["foo", [a:'a'], 1]
}
void "should accept 2 args, + 0 named args" () {
given:
def foo = Mock (C)
when:
def result = foo (1,2)
then:
1 * foo(1,2) >> { one, two -> ["foo", one, two]}
result == ["foo", 1, 2]
}
void "should accept 2 args, + 2 named args" () {
given:
def foo = Mock (C)
when:
def result = foo (1,2, a:'a', b:'b')
then:
1 * foo(1,2,a:'a', b:'b') >> { args, one, two -> ["foo", args, one, two]}
result == ["foo", [a:'a', b:'b'], 1, 2]
}
}