Reputation: 403
I have a method under test that contains the following snippet:
private void buildChainCode(List<TracedPath> lines){
for(TracedPath path : lines){
/.../
}
}
My unit test code looks like this:
public class ChainCodeUnitTest extends TestCase {
private @Mock List<TracedPath> listOfPaths;
private @Mock TracedPath tracedPath;
protected void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
}
public void testGetCode() {
when(listOfPaths.get(anyInt())).thenReturn(tracedPath);
ChainCode cc = new ChainCode();
cc.getCode(listOfPaths);
/.../
}
}
The problem is, that while running the test, the test code never enters the for loop. What when conditions should I specify, so that the for loop would be entered? Currently I have specified when(listOfPaths.get(anyInt())).thenReturn(tracedPath)
, but I guess it is never used.
Upvotes: 25
Views: 85386
Reputation: 6693
The Java For-Each loop used inside your buildChainCode
method isn't calling get()
, as you already figured out - it's using the iterator()
method defined in Collection<E>
, which List<E>
extends.
I really wouldn't recommend mocking the list. There's no advantage to it, unless you absolutely must check that the list was iterated through, and even then, it's better to assert on or verify the results of your class's behaviour given certain inputs.
Pass some implementation of List<E>
like LinkedList<E>
with tracedPath
in it.
Upvotes: 7
Reputation: 79875
Your problem is that when you use a collection in a for-each loop, its iterator()
method gets called; and you haven't stubbed that particular method.
Instead of mocking the list, I strongly recommend you just pass a real list, where the elements are just your mocked TracedPath
, as many times as you want it. Something like
listOfPaths = Arrays.asList(mockTracedPath, mockTracedPath, mockTracedPath);
Upvotes: 67