我很难在Groovy单元测试中理解有关Spock交互的内容。
我有以下类型:
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();
}
}
然后我编写了以下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
}
def "say hello"() {
expect:
foo.message.equals("hello")
}
def "say goodbye"() {
setup:
bar.getMessage() >> "goodbye"
expect:
foo.message.equals("goodbye")
}
}
代码在设置中创建模拟Bar
实例,初始化Bar.getMessage()
以返回hello
,并将其分配给新的Foo
实例。
第一项测试验证foo.getMessage()
是否等于hello
。
第二个测试尝试修改bar
模拟,以便它的getMessage
方法返回goodbye
。然后我们希望foo.getMessage()
(委托给bar.getMessage()
)将返回goodbye
。然而,测试失败如下:
FooSpec:说再见:26条件不满意
因为foo.message
仍然等于hello
。
我也尝试了以下内容:
def "say goodbye"() {
when:
bar.getMessage() >> "goodbye"
then:
foo.message.equals("goodbye")
}
和
def "say goodbye"() {
when:
no_op()
then:
bar.getMessage() >> "goodbye"
foo.message.equals("goodbye")
}
但是两个都失败了同样的你好并不等于再见消息。
我可能仍然在Mockito模式中思考,并假设交互相当于when(...).thenReturn(...)
表达式,后来的交互会覆盖早期的交互。
是否有一种简单的方法使用Spock在setup
方法中声明交互,然后在测试用例中覆盖该交互?或者我是否需要删除setup()
方法并基本上为每个测试用例添加setup:
块?
答案 0 :(得分:23)
这是一个棘手的问题。如docs中所述,在then-block中声明的交互优先于先前声明的交互。但是,在then-block中声明的交互范围限定为前一个时块。 (这允许有多个when-then对。)因此你的最后一次尝试不起作用,但以下将:
def setup() {
bar.message >> "hello"
}
def "say goodbye"() {
when:
def msg = foo.message
then:
bar.message >> "goodbye"
msg == "goodbye"
}
我同意在测试方法中声明的交互总是覆盖在setup方法中声明的交互。无论如何,覆盖交互的一个很好的替代方法是每个测试方法调用一个辅助方法来设置该测试方法的预期交互。