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

Ale*_*uya 19 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(){...}
}
Run Code Online (Sandbox Code Playgroud)

并测试代码如下:

  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
                                 }
                              )            
}
Run Code Online (Sandbox Code Playgroud)

我想验证eventBus.fireEvent(..)获取与类型的事件称为一次SaveCommentEvent和施工参数oldCommentnewComment.

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

更改封闭后的东西

{
   it.source.getClass()==SaveCommentEvent;
   it.oldComment==oldComment;  //old==old
   it.newComment==newComment   //new==new
}
Run Code Online (Sandbox Code Playgroud)

 {
    it.source.getClass()==Other_Class_Literal;
    it.oldComment==newComment;  //old==new
    it.newComment==oldComment   //new==old
  }
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*uya 36

我知道了:

    SaveCommentEvent firedEvent

    given:
     ...

    when:
     ....

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

  • Spock 似乎混淆了作为模拟返回值捕获的参数。对于其他人来说效果如何?@AlexLuya (2认同)

Ste*_* R. 12

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

    ...

    then:
    1 * eventBus.fireEvent(_) >> { SaveModelEvent event ->
        assert event.newModel == newModel
        assert event.oldModel == oldModel
    }
    0 * _
Run Code Online (Sandbox Code Playgroud)

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


jer*_*own 8

then:
     1*eventBus.fireEvent(
                            {
                               it.source.getClass()==SaveCommentEvent;
                               it.oldComment==oldComment;
                               it.newComment==newComment
                             }
                          )            
Run Code Online (Sandbox Code Playgroud)

在您的代码中,itGroovy Closure隐式变量引用,该引用引用了没有字段的模拟eventBus接口。您如何验证它们?

另外,我认为使用Spock Mocks必须发生的事件顺序不一定直观。我会在这里写下来,除非它不如肯尼斯·库森的解释那样好。

  • @jeremyjjbrown如果我没记错的话,您提供的代码不是100%正确。具体来说,只有在it.newComment == newComment检查不通过的情况下,测试才会失败。前两次检查不会对测试的通过或失败产生任何影响。@PeterNiederwieser在他的评论中暗示了这一点 (2认同)

小智 8

@Alex Luya 的想法相同,但将断言放在闭包中并assert在每个断言上使用。参见 Spock 框架参考文档

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