本文介绍了Spock:可以在测试用例中替换 setup() 中定义的交互吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力理解 Groovy 单元测试中有关 Spock 交互的一些内容.

I'm struggling to understand something about Spock interactions in a Groovy unit test.

我有以下类型:

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 测试:

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")
  }
}

该代码在设置中创建了一个模拟 Bar 实例,初始化 Bar.getMessage() 以返回 hello,并将其分配给一个新的 Foo 实例.

The code creates a mock Bar instance in the setup, initializes Bar.getMessage() to return hello, and assigns this to a new Foo instance.

第一个测试验证 foo.getMessage() 是否等于 hello.

The first test verifies that foo.getMessage() is equal to hello.

第二个测试尝试修改 bar 模拟,使其 getMessage 方法返回 goodbye.然后我们期望 foo.getMessage()(委托给 bar.getMessage())会返回 goodbye.但是测试失败如下:

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 条件不满足

因为 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不等于goodbye消息失败.

But both failed with the same hello does not equal goodbye message.

我可能仍在考虑 Mockito 模式,并假设交互相当于 when(...).thenReturn(...) 表达式,并且以后的交互将覆盖之前的交互.

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.

是否有一种简单的方法使用 Spock 在 setup 方法中声明交互,然后在测试用例中覆盖该交互?或者我是否需要删除 setup() 方法并基本上向每个测试用例添加一个 setup: 块?

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?

推荐答案

这是一个棘手的问题.如文档所述,在 then 块中声明的交互优先于声明的交互早些时候.但是,在 then-block 中声明的交互作用域为前一个 when-block.(这允许有多个 when-then 对.)因此您的最后一次尝试不起作用,但以下将:

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() 中定义的交互吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-30 05:55