Manually instantiating the @InjectMock annotated field

烈酒焚心 提交于 2020-02-21 13:13:46

问题


I have gone through some of the blogs in order to understand the basics of how Mockito annotations work.

However I am facing a doubt as to when does one go for manually instantiating the field annotated with @InjectMocks i.e

@InjectMocks
A a = new A();

And when does one rely on MockitoAnnotations.initMocks() functionality to do the same :

@InjectMocks
A a;

Does this depend on the JunitTestRunner that we employ to run the test cases or is it dependent on the Mockito framework version?


回答1:


It depends if you are using (declaring) the runner or not.

If you use the runner, you don't need to call MockitoAnnotations.initMocks() yourself - the runner calls it for you.

Usually we go for the runner. When you want to use other runners, though (like Spring's), you can call .initMocks() yourself.

Just to be clear, the MockitoAnnotations.initMocks(this) will:

  • Instantiate the field annotated with @InjectMocks
  • Create a mock version of every field annotated with @Mock
  • Inject the @Mocks in the @InjectMocks variable's fields (or call its constructors or use its setters - it depends on what kind of Dependency Injection you use)

Mockito runner, initMocks and rule code samples

The three code samples below should be equivalent.

With runner:

This first snippet uses the runner, making the call to initMocks() unnecessary.

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

    @Mock private MyDependency myDependency;
    @InjectMocks private MyClass myClass;

    @Test
    public void myClass_should_get_stuff_from_dependency() {
        when(myDependency.getStuff()).thenReturn("stuff!");

        assertThat(myClass.getDependencyStuff(), is("stuff!"));
    }
}

Without runner + with manual call to .initMocks():

This other does not use the runner, thus the need for the setUp() method calling our initMocks() friend.

// notice there is no runner
public class MyClassTest {

    @Mock private MyDependency myDependency;
    @InjectMocks private MyClass myClass;

    // but now you have to call initMocks() yourself
    @Before
    public void setUp() throws Exception {
          MockitoAnnotations.initMocks(this);
    }

    @Test
    public void myClass_should_get_stuff_from_dependency() {
        when(myDependency.getStuff()).thenReturn("stuff!");

        assertThat(myClass.getDependencyStuff(), is("stuff!"));
    }
}

Without runner or manual call, using @Rule:

Finally, as pointed out in the comments (thanks @StefanBirkner), since version 1.10.17, there is also the possibility of using a JUnit @Rule called MockitoRule:

public class MyClassTest {

    @Rule
    public MockitoRule rule = MockitoJUnit.rule();

    @Mock private MyDependency myDependency;
    @InjectMocks private MyClass myClass;

    @Test
    public void myClass_should_get_stuff_from_dependency() {
        when(myDependency.getStuff()).thenReturn("stuff!");

        assertThat(myClass.getDependencyStuff(), is("stuff!"));
    }
}



回答2:


Thanks for your valuable thoughts. But still it doesn't answer the question as to why one goes for manually instantiating the field annotated with @InjectMocks when the instantiation should be handled by a call to MockitoAnnotations.initMocks().

I get the following error when trying to run the test file :

Caused by: org.mockito.exceptions.base.MockitoException: Field 'student' annotated with @InjectMocks is null. Please make sure the instance is created before MockitoAnnotations.initMocks(); Example of correct usage:

class SomeTest {
    @InjectMocks private Foo foo = new Foo();

    @Before public void setUp() {
        MockitoAnnotations.initMock(this);

I searched further and found out that the error is thrown if one is using an older version of Mockito framework.

http://myshittycode.com/category/testing/mockito/



来源:https://stackoverflow.com/questions/33397643/manually-instantiating-the-injectmock-annotated-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!