Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stub a method of an class annotated with @InjectMocks?

Below MyDictionary.get method uses the injected map by calling map.get.

Just of curiosity I stubbed the MyDictionary.get method, like I always do with mocks and spies, so I overwrite the injection.

But this only works when MyDictionary.get indeed calls map.get. If map.get returns some string (the empty string here), the stub Mockito.when does not work. The behavior is as if it is not there. In the assert line, dictionary.get("key") equals the empty string. This is what I do not understand.

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {

    @Mock
    Map<String, String>map;

    @InjectMocks
    MyDictionary dictionary;

    @Test
    public void testMyDictionary(){
        Mockito.when(dictionary.get("key")).thenReturn("value");
        Assert.assertEquals("value", dictionary.get("key"));
    }

    private static class MyDictionary{
        private Map<String, String> map; 
        public String get(String key){
            return map.get(key);
// or,
            return "";
        }
    }
}
like image 826
ericj Avatar asked Mar 02 '17 16:03

ericj


People also ask

What does InjectMocks annotation do?

@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.

What is the difference between @mock and @InjectMocks?

@InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock annotations into this instance. @Mock is used to create mocks that are needed to support the testing of the class to be tested. @InjectMocks is used to create class instances that need to be tested in the test class.

Does InjectMocks inject spy?

Again, note that @InjectMocks will only inject mocks/spies created using the @Spy or @Mock annotation.

Can we use mock and InjectMocks together?

A mock doesn't have any real implementation. @InjectMocks would try to find and call setters for whatever mock objects have already been created and pass them in.


1 Answers

I am really surprised that you do not get a MissingMethodInvocationException which is thrown when you try to stub a method of an object not being a @Mock or a @Spy.

The dictionary instance is just a regular instance of a class here not proxied by Mockito (because of the fact that only @InjectMocks annotation is used).

Another surprise is that you do not get a null when the map.get is triggered as default return value for a String returning method is null.

Anyway..

If you want to stub methods of the `dictionary' instance you have to configure your test class as follows:

@InjectMocks
@Spy
MyDictionary dictionary;

@Test
public void testMyDictionary(){
    doReturn("value").when(dictionary).get("key);
    Assert.assertEquals("value", dictionary.get("key"));
}
like image 121
Maciej Kowalski Avatar answered Nov 09 '22 23:11

Maciej Kowalski