Как сделать захват аргументов с помощью фреймворка spock?

У меня есть Java-материал вроде этого:

public interface EventBus{
    void fireEvent(GwtEvent<?> event);
}


public class SaveCommentEvent extends GwtEvent<?>{
    private finalComment oldComment;
    private final Comment newComment;

    public SaveCommentEvent(Comment oldComment,Comment newComment){
        this.oldComment=oldComment;
        this.newComment=newComment;
    }

    public Comment getOldComment(){...}
    public Comment getNewComment(){...}
}

и тестовый код:

  def "...."(){
     EventBus eventBus=Mock()
     Comment oldComment=Mock()
     Comment newCommnet=Mock()

     when:
         eventBus.fireEvent(new SaveCommentEvent(oldComment,newComment))

     then:
         1*eventBus.fireEvent(
                                {
                                   it.source.getClass()==SaveCommentEvent;
                                   it.oldComment==oldComment;
                                   it.newComment==newComment
                                 }
                              )            
}

Я хочу проверить, что eventBus.fireEvent(..) вызывается один раз с событием с типом SaveCommentEvent и параметрами конструкции oldComment и newComment.

Код работает без ошибок, но проблема такова:

После изменения закрывающего материала из

{
   it.source.getClass()==SaveCommentEvent;
   it.oldComment==oldComment;  //old==old
   it.newComment==newComment   //new==new
}

To

 {
    it.source.getClass()==Other_Class_Literal;
    it.oldComment==newComment;  //old==new
    it.newComment==oldComment   //new==old
  }

Тем не менее, код работает без ошибок? По-видимому, закрытие не делало то, что я хочу, поэтому вопрос: как сделать захват аргументов?

Ответ 1

Я понял:

    SaveCommentEvent firedEvent

    given:
     ...

    when:
     ....

    then:
    1 * eventBus.fireEvent(_) >> {arguments -> firedEvent=arguments[0]}
    firedEvent instanceof SaveModelEvent
    firedEvent.newModel == newModel
    firedEvent.oldModel == oldModel

Ответ 2

then:
     1*eventBus.fireEvent(
                            {
                               it.source.getClass()==SaveCommentEvent;
                               it.oldComment==oldComment;
                               it.newComment==newComment
                             }
                          )            

В вашем коде it есть Groovy Clocure Implicit Variable ссылка на mock eventBus Interface, который не имеет полей. Как вы могли их проверить?

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

Ответ 3

В ответе @alex-luya выше я обнаружил, что для переменной firedEvent требуется аннотация @Shared.

Затем я могу захватить значение и выполнить мои проверки значения за пределами замыкания.

Ответ 4

Если вы фиксируете аргумент в методе в явном блоке взаимодействия, тогда аргумент доступен вне замыкания взаимодействия, но не внутри замыкания.

Например:

   SaveCommentEvent firedEvent = null

   void captureFiredEvent(EventBus eventBus) {
      1 * eventBus.fireEvent(_) >> {arguments -> firedEvent=arguments[0]}
      // firedEvent *cannot* be checked here. The following line will fail:
      // firedEvent instanceof SaveModelEvent
   }

   void "test eventBus"() {

     given:
       ...

     when:
       ....

     then:
       interaction { captureFiredEvent(eventBus) }
       // firedEvent can be checked here
       firedEvent instanceof SaveModelEvent

   }