【问题标题】:Problem with ArgumentCaptor and consecutive call to same methods (bug or feature?)ArgumentCaptor 问题和对相同方法的连续调用(错误或功能?)
【发布时间】:2010-07-26 09:35:27
【问题描述】:

我遇到了 ArgumentCaptor 无法记录 多次调用同一方法时的参数。 基本上这似乎不起作用:

List<Dummy> mList = mock(List.class);
Dummy dummy = new Dummy();
when(mList.get(anyInt())).thenReturn(dummy);

Dummy d = mList.get(12);
d.setName("John");
mList.add(d);

Dummy g = mList.get(10);
g.setName("Ben");
mList.add(g);
...

verify(mymock, times(3)).doStuff(captor.capture)); 
assertEquals("John", captor.getAllValues().get(0).getName()); 
assertEquals("Ben", captor.getAllValues().get(1).getName()); 
assertEquals("Don", captor.getAllValues().get(2).getName()); 

getName() 的值始终设置为“Don”。 我也尝试过使用 InOrder,结果相同。

功能(和我一样愚蠢)还是错误?

为了更好地解释这个问题,我创建了一个用例: http://pastebin.com/RE1UzJ4F

干杯

【问题讨论】:

    标签: java unit-testing mockito


    【解决方案1】:

    iwein 是正确的;但是,在某些情况下(例如嵌入式系统),内存不足,您不想使用或无法使用不变性。

    我发现的一种解决方法是为每次调用使用不同的模拟,然后验证每个都有一次调用的模拟列表。

    List<Mock> mocks = new ArrayList<Mock>();
    ...init list w/ mocks using for loop...
    List<Object[]> expectedArgs = new ArrayList<Object[]>();
    ..init list w/ desired args...
    
    mocks.get(0).callMethod(1, 2);
     ...do that some more...
    
    for(int i = 0; i < mocks.size(); i++) {
         Object[] desiredArgs = expectedArgs.get(i);
         verify(mocks.get(i)).callMethod((int) desiredArgs[0], (int) desiredArgs[1]);
     }
    

    它没有那么漂亮,但您不必以这种方式使您的类不可变。

    【讨论】:

      【解决方案2】:

      ArgumentCaptor 的 java 文档建议您尝试什么,所以我会说这是一个错误。但是,这是您代码中的错误。

      问题是您每次调用 setName(..) 时都在更改 同一个 dummy 的名称。我建议您使 Dummy 不可变 并尽可能避免设置器。这样可以避免这些类型的错误。

      如果你不能让你的 Dummy 不可变来强制执行这个问题,你至少应该从每个 get 传递一个不同的实例。在做

      when(mList.get(anyInt())).thenReturn(new Dummy(), new Dummy(), new Dummy());
      

      会解决问题。

      【讨论】:

      • 是的,当然,测试代码只是解释问题的一种方式。
      • 我的意思是,唯一的问题实际上出在您的代码中,而不是在 Mockito 中。这就是你想要解释的(在那种情况下,我很抱歉我错过了)?
      • 我已将您的样本固定在 pastebin 中(虽然没有编译)。
      【解决方案3】:

      我遇到了这个问题,最终使用了atLeastOnce,就像这样:

      private ActionRequest getRequestedAction() {
          ArgumentCaptor<ActionRequest> captor = ArgumentCaptor.forClass(ActionRequest.class);
          verify(adapter, atLeastOnce()).requestAction(captor.capture());
          return captor.getValue();
      }
      

      【讨论】:

        猜你喜欢
        • 2011-04-11
        • 1970-01-01
        • 2020-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多