我在理解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:say goodbye:26 Condition not satisfied
因为 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")
}
但两者都出现了相同的“hello does not equal goodbye”的错误信息。
我可能还在以Mockito的模式思考,并假设一个交互就是等价于一个when(...).thenReturn(...)
表达式,后续的交互会覆盖之前的交互。
是否有一种简单的方式可以使用Spock在setup
方法中声明一个交互,然后在测试用例中覆盖该交互?还是说我需要删除setup()
方法,基本上为每个测试用例添加一个setup:
块?
setup()
方法并更改我的测试方法以直接初始化它们的状态(这也是因为我经常在测试方法中使用where:
块,并惊讶地发现setup()
方法在where:
块之后被调用)。我认为我能够理解您上面的示例,但它不直观(对我来说它仍然看起来像then:
块中的设置代码)。 - John Q Citizengiven:
块中。 - Zorobay