emsiiggy
emsiiggy

Reputation: 343

HashMap doesn't add values after @InjectMocks. The hashmap is inside class with the annotation

The problem is that nothing is added to my cache. My class is much bigger so I provide here to minimum example that should reproduce the problem. Let's say I have a dictionary class, which uses some initialService to return hashMap with initial values.

public class Dictionary() {
    @Inject
    private InitialService initialService;
    
    private Map<String, String> map;
    
    public Map<String, String> constructMap() {     
        HashMap<String, String> initialMap = initialService.getHashMap("initialKey", "initialValue");
        return initialMap;
    }
    
    public void saveConstructedMap() {
        map = constructMap();
    }
    
    public Map<String, String> getMap() {
        return map;
    }
}

Then I have a test with mockito. So firstly I save the map with method saveConstructedMap() then I get the map with getMap() and then I add there value. I would expect the value to be there but the map is empty. Even if I don't save it to new value but will do the put on getMap() so getMap().put(...)

public class DictionaryTest() {
    @Mock
    private InitialService initialService;
    
    @InjectMocks
    private Dictionary dictionary;
    
    public void test() {
        dictionary.saveConstructedMap();
        HashMap<String, String> myMap = dictionary.getMap();
        myMap.put("key","value");
        assertTrue(myMap.containsKey("key")); //returns false (the entry is not added)
    }
}

From what I understand the Mock just mocks the class so its empty inside, but @InjectMocks injects the specified mock and creates an object but in normal way (like I would do it with constructor for the Dictionary. So all the methods and fields should behave as in normal class, not test one. Did i misunderstand something here?) Does anyone know what should i do to achieve what i want?

Of course i have initMocks(this) in the setUp() method which is annotated with @Before,

Upvotes: 0

Views: 745

Answers (1)

amseager
amseager

Reputation: 6391

Actually, DictionaryTest can't be compiled, e.g. because of HashMap<String, String> myMap = dictionary.getMap(); line (should be Map<String, String>). Probably you've written it just for the question.

Nevertheless, the main idea of mock testing is to provide a custom implementation of mocked class' methods. In this case, you should do it for the getHashMap method of InitialService mock. The example is below:

Map<String, String> initialMap = new HashMap<>();
initialMap.put(initialKey, initialValue);
Mockito.when(initialService.getHashMap("initialKey", "initialValue")).thenReturn(initialMap);

If you don't do that, Mockito will set the default value as a result of the method (in this case, it would be null):

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.

Another approach is to make a partial mock and use real implementations of its methods where needed. But don't take advantage of it.

Upvotes: 0

Related Questions