单元测试 – Spock:在测试用例中可以替换setup()中定义的交互吗?

在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方法返回再见。然后我们预期,foo.getMessage()(代表bar.getMessage())然后会再见。但测试失败如下:

FooSpec:说再见:26条件不满意

因为foo.message仍然等于你好。

我也尝试了以下:

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模式,并假设一个交互是相当于一个(…),thenReturn(…)表达式,后来的交互将覆盖早期的交互。

有没有一种简单的方式使用Spock来在安装方法中声明交互,然后在测试用例中覆盖该交互?或者我需要删除setup()方法,并且基本上添加一个setup:block到每个测试用例?

解决方法

这是一个棘手的事情。如 docs所述,在一个块中声明的交互优先于先前声明的交互。然而,在一个块中声明的交互作用域为前一个块。 (这允许有多个when-then对)。因此,你最后一次尝试不起作用,但是以下将会:

def setup() {
    bar.message >> "hello"
}

def "say goodbye"() {
    when:
    def msg = foo.message

    then:
    bar.message >> "goodbye"
    msg == "goodbye"
}

我同意在测试方法中声明的交互将始终覆盖在安装方法中声明的交互。无论如何,替代交互的好方法是每个测试方法调用一个辅助方法来设置该测试方法的预期交互。

相关文章

背景:    8月29日,凌晨4点左右,某服务告警,其中一个...
https://support.smartbear.comeadyapi/docs/soapui/steps/g...
有几个选项可用于执行自定义JMeter脚本并扩展基线JMeter功能...
Scala和Java为静态语言,Groovy为动态语言Scala:函数式编程,...
出处:https://www.jianshu.com/p/ce6f8a1f66f4一、一些内部...
在运行groovy的junit方法时,报了这个错误:java.lang.Excep...