Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking two maps in a class

Tags:

java

mockito

maps

I have to test a class that injects two maps with springs. I would like to mock both maps. I use the Mock notation as follows :

@Mock
private Map<String, Integer> map1;

@Mock
private Map<String, Date> map2;

but I get the following error :

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Date

It seems that only the first mocked map is used for both maps.

What am I doing wrong ?

like image 287
Pierre Girardeau Avatar asked Nov 17 '25 22:11

Pierre Girardeau


1 Answers

As long as the type of the two fields are the same, mockito doesn't know to how to inject your mock by types. So it tries to inject it by name. In this case, looks like the name of fields in your class under test does not match to the mock object that you have created. Here is the doc for @InjectMocks:

Field injection; mocks will first be resolved by type (if a single type match injection will happen regardless of the name), then, if there is several property of the same type, by the match of the field name and the mock name.

You can either rename your filed or use explicit mock names:

@Mock(name="foo")
private Map<String, Integer> map1;

@Mock(name="bar")
private Map<String, Date> map2;

But I don't think that this is the best solution. In case if the filed name will be renamed you will got the false negative test result: functionality works correct but test fails.

For me, the best solution is to refactor your code so the class under test receive the dependencies in the constructor. After that you can mock it like this:

@Mock
private Map<String, Integer> map1;

@Mock
private Map<String, Date> map2;

private ClassUnderTets cut;

@Before
public void setUp() throws Exception {
    cut = new ClassUnderTets(map1, map2);
}

Or even:

@Mock
private Map<String, Integer> map1;

@Mock
private Map<String, Date> map2;

@InjectMocks
private ClassUnderTets cut;

As mentioned in the docs:

Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only

like image 88
Sergii Bishyr Avatar answered Nov 19 '25 11:11

Sergii Bishyr