Problem with ArgumentCaptor and sequential call of the same methods (error or function?)

I have a problem with an ArgumentCaptor that cannot write arguments when calling the same method multiple times. This basically does not work:

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()); 

The value of getName () is always set to Don. I also tried using InOrder with the same result.

Function (and me stupiud) or error?

To better explain the problem, I set a use case: http://pastebin.com/RE1UzJ4F

Greetings

+4
source share
3 answers

The java document for ArgumentCaptor suggests what you are trying, so I would say that this is a mistake. However, this is a mistake in your code.

The problem is that you change the name of the same dummy every time you call setName (..). I suggest you make Dummy unchanged and avoid setters wherever you are. This will avoid such errors.

If you cannot make your Dummy immutable to cause a problem, you should at least pass a different instance from each get. Performance

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

To solve a problem.

+2
source

iwein is correct; however, there are some situations (such as embedded systems) in which there is not enough memory and you do not want to use or cannot use immutability.

The workaround I found is to use a different layout for each call, and then check the list of poppies, each of which has one call.

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

It is not so pretty, but you do not need to make your classes immutable in this way.

+2
source

I had this problem and ended up using atLeastOnce , for example:

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

All Articles