Manually instantiating the @InjectMock annotated field
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
@Mock
s 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!"));
}
}
In general, the decision to instantiate an object which is annotated with @InjectMocks
or not is a code style choice. In the majority of cases there will be no difference as Mockito is designed to handle both situations.
However, there is some differences which I have outlined below.
@InjectMocks
decouples a test from changes to the constructor.
In the same way using a Dependency Injection framework decouples your production code from changes to the constructor. Allowing Mockito to instantiate an instance of the class for you decouples your test code from changes to the constructor. This means any future changes to the class constructor can be done without causing compilation errors in the unit test.
In my opinion this is the biggest difference and the biggest advantage of @InjectMocks
.
Mockito will always call the "biggest" constructor
Note: This difference is only relevant when the code you are working with does not follow best practices.
When there is multiple constructors in a class, Mocktio will call the constructor with the most parameters, the "biggest" constructor.
This only has an impact when,
- A "small" constructor contains logic.
- This logic is required for the class to function correctly.
- The "biggest" constructor does not invoke the next "smallest" constructor.
This is considered bad practice because,
- Placing logic within a constructor should be avoided whenever possible.
- When there is multiple constructors within a class each constructor should first invoke the constructor before it.