3
Mockito.when(metadataDao.getStuff(Mockito.anyInt()).get(Mockito.anyInt()))
               .thenReturn(returnedVariable);

I'm getting the following error:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
    at java.util.LinkedList.get(LinkedList.java:476)
    at 

Why can't I use the matchers?

durron597
  • 31,968
  • 17
  • 99
  • 158
Grégoire Borel
  • 1,880
  • 3
  • 33
  • 55
  • For future reference, your questions will probably get noticed sooner if you always include the primary language tag in addition to your tag like [tag:mockito]. – durron597 Aug 24 '15 at 16:04

2 Answers2

9

Mockito.anyInt() works via side-effects; when it passes the value to a real class, it essentially sends 0.

It looks like metadataDao.getStuff is returning a real LinkedList, with size 0. Then, you send what amounts to 0 to that real LinkedList, which calls the real get method with size 0, and you get the normal error you expect.

You can avoid problems like this by not ever using chained method calls inside Mockito, in other words, never do:

when(obj.methodOne().methodTwo())

Instead, just use one method call. In your example, this might be:

List<MyObj> mockList = Mockito.mock(List.class);
Mockito.when(metadataDao.getStuff(Mockito.anyInt()).thenReturn(mockList);
Mockito.when(mockList.get(Mockito.anyInt())).thenReturn(returnedVariable);

Also note that, as @JeffBowman points out in the comments, you should never be mocking List when a real List will do.

durron597
  • 31,968
  • 17
  • 99
  • 158
  • 1
    +1 for the general statement of not chaining method calls, though it's almost never a good idea to mock a List where a real one would work. – Jeff Bowman Aug 24 '15 at 16:37
  • @JeffBowman I completely agree; as I said to Mark Peters I didn't have enough information about OP's code to do much else. – durron597 Aug 24 '15 at 16:45
  • Absolutely; that comment was more for the OP's sake than yours. :) – Jeff Bowman Aug 24 '15 at 16:45
2

While @durron597 has the right analysis, there is a way to configure Mockito to handle your current code, by configuring your mock with Mockito.RETURNS_DEEP_STUBS. That way getStuff will automatically return a mock which can be used for chaining.

In both cases, this behavior of "deep" mocking is discouraged by the Mockito team. Just an excerpt from their sermon (found in the link above):

WARNING: This feature should rarely be required for regular clean code! Leave it for legacy code. Mocking a mock to return a mock, to return a mock, (...), to return something meaningful hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • There's a reason I didn't recommend `Mockito.RETURNS_DEEP_STUBS` ;) – durron597 Aug 24 '15 at 16:03
  • @durron597: Your suggestion isn't any better though. The reason it's warned against is because it's symptomatic of bad code. Your approach doesn't change that; you're still doing deep mocks, you're just doing it in a more laborious way. – Mark Peters Aug 24 '15 at 16:03
  • I agree, but OP didn't include the code of the thing he's testing for me to be able to suggest a refactoring. Anyway I agree with you, +1. – durron597 Aug 24 '15 at 16:04