Spock:可以在测试用例中替换setup()中定义的交互吗? [英] Spock: can an interaction defined in setup() be replaced in a test case?
问题描述
我有以下几种类型:
public interface Bar {
public String getMessage();
}
公共类Foo {
私人酒吧;
public void setBar(Bar bar){
this.bar = bar;
}
public String getMessage(){
return bar.getMessage();
}
}
然后我写了下面的Groovy / Spock测试:
class FooSpec extends Specification {
private bar bar;
private Foo foo;
def setup(){
bar = Mock(Bar){getMessage()>> hello}
foo = new Foo()
foo.bar = bar
}
defsay hello(){
expect:
foo.message.equals(hello)
}
defsay goodbye(){
setup:
bar.getMessage() >> goodbye
expect:
foo.message.equals(goodbye)
}
}
代码在设置中创建一个模拟的 Bar
实例,初始化 Bar.getMessage ()
返回 hello
,并将其分配给新的 Foo
实例。
$ b
第一个测试验证 foo.getMessage()
等于 hello code>。
第二个测试尝试修改 bar
mock,使其 getMessage
方法返回再见
。然后我们期望 foo.getMessage()
(它委托给 bar.getMessage()
)然后返回再见
。然而,测试失败如下:
FooSpec:说再见:26条件不满意
因为
foo.message
仍然等于 hello
。 我也尝试了以下方法:
defsay goodbye(){
when:
bar.getMessage()>> goodbye
then:
foo.message.equals(goodbye)
}
和:
defsay goodbye(){
when :
no_op()
then:
bar.getMessage()>> goodbye
foo.message.equals(goodbye)
}
但是,两者都失败了,因为
我可能还在考虑Mockito模式,并假设当(...)。thenReturn(...)表达式相互作用时,相当于,并且以后的交互会覆盖以前的交互。
是否有一种简单的方法使用Spock在 setup
方法中声明交互,然后在测试用例中覆盖该交互?或者是否需要删除 setup()
方法,并基本为每个测试用例添加一个 setup:
块?
这是一个棘手的问题。正如文档中所述,在then-block中声明的交互优先于声明的交互早。然而,在then块中声明的交互作用范围是前一个when块。 (这允许有多个时间对)。因此,您最后一次尝试不起作用,但以下内容将会:
def setup(){
bar.message>> hello
}
defsay goodbye(){
when:
def msg = foo.message
then:
bar.message>> goodbye
msg ==goodbye
}
我同意在测试方法中声明的交互总是会覆盖在安装方法中声明的交互。无论如何,重写交互的一个很好的选择是每个测试方法调用一个帮助方法,为该测试方法设置预期的交互。
I'm struggling to understand something about Spock interactions in a Groovy unit test.
I have the following types:
public interface Bar {
public String getMessage();
}
public class Foo {
private Bar bar;
public void setBar(Bar bar) {
this.bar = bar;
}
public String getMessage() {
return bar.getMessage();
}
}
and I then wrote the following Groovy/Spock test:
class FooSpec extends Specification {
private Bar bar;
private Foo foo;
def setup() {
bar = Mock(Bar) { getMessage() >> "hello" }
foo = new Foo()
foo.bar = bar
}
def "say hello"() {
expect:
foo.message.equals("hello")
}
def "say goodbye"() {
setup:
bar.getMessage() >> "goodbye"
expect:
foo.message.equals("goodbye")
}
}
The code creates a mock Bar
instance in the setup, initializes Bar.getMessage()
to return hello
, and assigns this to a new Foo
instance.
The first test verifies that foo.getMessage()
is equal to hello
.
The second test tries to modify the bar
mock so that it's getMessage
method returns goodbye
. We then expect that foo.getMessage()
(which delegates to bar.getMessage()
) would then return goodbye
. However the test fails as follows:
FooSpec:say goodbye:26 Condition not satisfied
because foo.message
is still equal to hello
.
I also tried the following:
def "say goodbye"() {
when:
bar.getMessage() >> "goodbye"
then:
foo.message.equals("goodbye")
}
and:
def "say goodbye"() {
when:
no_op()
then:
bar.getMessage() >> "goodbye"
foo.message.equals("goodbye")
}
But both failed with the same hello does not equal goodbye message.
I'm probably still thinking in Mockito mode, and assume that an interaction is the equivalent of a when(...).thenReturn(...)
expression, and that later interactions would override earlier interactions.
Is there a simple way using Spock to declare an interaction in a setup
method, then override that interaction in a test case? Or do I need to remove the setup()
method and basically add a setup:
block to each test case?
That's a tricky one. As stated in the docs, interactions declared in a then-block have precedence over interactions declared earlier. However, interactions declared in a then-block are scoped to the previous when-block. (This allows to have multiple when-then pairs.) Hence your last try doesn't work, but the following will:
def setup() {
bar.message >> "hello"
}
def "say goodbye"() {
when:
def msg = foo.message
then:
bar.message >> "goodbye"
msg == "goodbye"
}
I agree that it would be good for interactions declared in test methods to always override interactions declared in setup methods. Anyway, a good alternative to overriding interactions is for each test method to call a helper method that sets up the expected interactions for that test method.
这篇关于Spock:可以在测试用例中替换setup()中定义的交互吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!