Подтвердить что ты не робот

Spock: можно ли заменить взаимодействие, определенное в setup() в тестовом примере?

Я пытаюсь понять что-то о взаимодействиях Спока в 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:

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

Код создает экземпляр mock 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: к каждому тестовому примеру?

4b9b3361

Ответ 1

Это сложная штука. Как указано в docs, взаимодействия, объявленные в then-блоке, имеют приоритет над ранее объявленными взаимодействиями. Однако взаимодействия, объявленные в then-блоке, привязаны к предыдущему if-block. (Это позволяет иметь несколько пар "когда-то".) Следовательно, ваша последняя попытка не работает, но следующее:

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

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

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

Я согласен с тем, что было бы полезно, чтобы взаимодействия, объявленные в методах тестирования, всегда перекрывали взаимодействия, объявленные в методах настройки. Во всяком случае, хорошей альтернативой переопределяющим взаимодействиям является для каждого метода тестирования вызов вспомогательного метода, который устанавливает ожидаемые взаимодействия для этого метода тестирования.