4

我在多次调用同一方法时遇到 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

干杯

4

3 回答 3

2

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

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

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

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

会解决问题。

于 2010-07-26T11:09:08.893 回答
2

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]);
 }

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

于 2012-07-03T00:35:38.950 回答
1

我遇到了这个问题并最终使用atLeastOnce,如下所示:

private ActionRequest getRequestedAction() {
    ArgumentCaptor<ActionRequest> captor = ArgumentCaptor.forClass(ActionRequest.class);
    verify(adapter, atLeastOnce()).requestAction(captor.capture());
    return captor.getValue();
}
于 2012-07-11T01:48:28.343 回答