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 doc は、あなたが何をしようとしているのかを示唆しているので、これはバグだと思います。ただし、これはコードのバグです。

問題は、setName(..) を呼び出すたびに同じダミーの名前を変更していることです。Dummy を不変にし、できる限りセッターを避けることをお勧めします。これにより、これらのタイプのバグを回避できます。

問題を強制するためにダミーを不変にすることができない場合は、少なくとも各 get から異なるインスタンスを渡す必要があります。やっている

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

問題を解決します。

于 2010-07-26T11:09:08.893 に答える
2

iwein は正しいです。ただし、メモリが不足していて不変性を使用したくない、または使用できない状況 (組み込みシステムなど) があります。

私が見つけた回避策は、呼び出しごとに異なるモックを使用し、それぞれが 1 つの呼び出しを持つモックのリストを検証することです。

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 に答える