Reputation: 778
Why is mockMap
using the real implementation?
How do I prevent this?
In method testFirstKeyMatch
when(mockMap.keySet().toArray()[0])...
throws ArrayIndexOutOfBoundsException: 0 when running the test.
MaxSizeHashMap is a LinkedHashMap with max size of 7, throws an IndexOutOfBoundsException when I attempt to put more into.
Profile keeps track of something not essential for this.
SuperClass.java
public class SuperClass {
protected String[] days;
protected MaxSizeHashMap<String, String> map;
public SuperClass() {
days = new String[7];
map = new MaxSizeHashMap<String, String>();
//...
}
void updateDays() {
cal = Calendar.getInstance();
for (int i = 0; i < 7; i = i + 1) {
//adds short names "Mon", "Tue", ... to days
days[i] = cal.getDisplayName(Calendar.DAY_OF_WEEK,
Calendar.SHORT, Locale.US);
cal.add(Calendar.DATE, 1);
}
}
void firstKeyMatch(Profile profile) {
updateDays();
//checks if first key of map is not same as days[0]
if (days[0] != map.keySet().toArray()[0]) {
profile.add();
//...
}
}
}
SuperClassTest.java
@RunWith(MockitoJUnitRunner.class)
public class SuperClassTest {
@InjectMocks
private SuperClass spr = new SuperClass();
@Mock
private MaxSizeHashMap<String, String> mockMap;
@Mock
private Profile mockProfile;
//...
@Test
public void testFirstKeyMatch() {
when(mockMap.keySet().toArray()[0]).thenReturn(spr.days[0]);
verify(mockProfile, never()).add();
}
}
Upvotes: 5
Views: 4786
Reputation: 15508
As per the documentation, mockito's implicit behaviour for a mock is to return default values.
By default, for all methods that return a value, a mock will return either null, a primitive/primitive wrapper value, or an empty collection, as appropriate. For example 0 for an int/Integer and false for a boolean/Boolean.
In consequence, your mockMap.keySet()
will return an empty hash-set, which you then convert to an empty array and try to retrieve the (non-existent) first element, hence the IOOBE.
In conclusion, mockito is not using the real implementation, but it's behaving normally as it's supposed to.
You did not post the entire constructor of SuperClass
, but probably after you instantiate the map, you also populate it with values. If that's true, then one can argue that the exception is actually proof that mockito does not use the real implementation, because you'd really be getting the first element.
As for the solutions, well it's already been suggested to return your own hash set with whatever data you require (credits go to Abubakkar):
when(mockMap.keySet()).thenReturn(new HashSet(Arrays.asList("your day string")));
Upvotes: 3
Reputation: 6577
To redirect all mockMap.keySet().toArray()[i]
calls to spr.days[i]
, you can tell mockMap
to return the days
array when someone requests the key set.
Set keySetMock = mock(Set.class);
when(keySetMock.toArray()).thenReturn(spr.days);
when(mockMap.keySet()).thenReturn(keySetMock);
Upvotes: 1