如何使用spock框架进行参数捕获?

时间:2014-03-01 06:54:33

标签: 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且构造参数oldCommentnewComment的事件中被调用一次。

代码运行没有错误,但问题是:

更改封面内容后
{
   it.source.getClass()==SaveCommentEvent;
   it.oldComment==oldComment;  //old==old
   it.newComment==newComment   //new==new
}

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

仍然,代码运行没有错误?显然关闭没有做我想要的,所以问题是:如何进行参数捕获?

6 个答案:

答案 0 :(得分:33)

我明白了:

    SaveCommentEvent firedEvent

    given:
     ...

    when:
     ....

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

答案 1 :(得分:4)

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

在您的代码中it是对模拟eventBus接口的Groovy Closure Implicit Variable引用,该接口没有字段。你怎么验证他们?

另外,我认为使用Spock Mocks必须发生的事件顺序不一定直观。我会在这里写下来,除非它不如Kenneth Kousen's explanation那么好。

答案 2 :(得分:0)

在上面@ alex-luya的回答中,我发现变量firedEvent需要@Shared注释。

然后,我可以捕获值并在闭包之外对值进行检查。

答案 3 :(得分:0)

如果您在explicit interaction block中的方法中捕获参数,则该参数在交互闭包的外部 可用,但在闭包的 inside 中不可用。

例如:

   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

   }

答案 4 :(得分:0)

@Alex Luya的想法相同,但是将这些断言放在结尾并在每个断言上使用assert。 cf. Spock Framework Reference Documentation

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

答案 5 :(得分:0)

在 2021 年(7 年后),可以使用 groovy (2.5) 执行以下操作:

    ...

    then:
    1 * eventBus.fireEvent(_) >> { SaveModelEvent event ->
        event.newModel == newModel
        event.oldModel == oldModel
    }
    0 * _

...这对我来说感觉更方便并且节省了一两行。 :)