代码之家  ›  专栏  ›  技术社区  ›  Luciano Fiandesio

ArgumentCaptor和对相同方法的连续调用出现问题(bug或feature?)

  •  4
  • Luciano Fiandesio  · 技术社区  · 14 年前

    我有个问题,因为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”。 我也尝试过使用inoder,结果是一样的。

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

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

    干杯

    3 回复  |  直到 14 年前
        1
  •  2
  •   Patrick    12 年前

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

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

    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
  •  2
  •   iwein    12 年前

    ArgumentCaptor的Javadoc建议您尝试什么,所以我认为这是一个bug。但是,这是代码中的一个bug。

    问题是你正在更改 相同的 每次调用setName(..)时都是dummy。我建议你做个假人 不变的 尽可能避免二传手。这将避免这些类型的错误。

    如果不能使虚拟对象不可变以强制解决问题,那么至少应该从每个get传递一个不同的实例。做

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

    会解决问题的。

        3
  •  1
  •   Viktor Nordling    12 年前

    我有这个问题,最后用了 atLeastOnce ,就像这样:

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