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();
}
}
Mockito allows us to partially mock an object. This means that we can create a mock object and still be able to call a real method on it. To call a real method on a mocked object we use Mockito's thenCallRealMethod().
The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called. We don't need to do anything else to this method before we can use it.
We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object. We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.
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")));
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With