Mockito injection not working for constructor AND setter mocks together

This is wanted by mockito framework. See this Github Issue.

I found out that it is possible to bypass this behaviour if you extend your testclass from any other class (i created an empty class with a meaningful name and a small comment).

I don't know exactly why but i belief that in case of a extended test class any internal routine of mockito will do the injection twice. Maybe because mockito goes throught the class hirachy and has a internal routine which injects throught constructor on the first time and second time he makes the setter/property injection. Just a guess. If i have time i will have a look into the mockito implementation.


Although Constructor injection is highly recommended, and I'd strongly advise against mixing injection methods, I've come across such a class which I can't refactor. To get around the problem, call initMocks explicity. For example:

@InjectMocks
private ThingWithMixedDependencies thing;

@Mock
private FieldInjected secondDependency;

@BeforeEach
void setUp() {
  // This cannot be a mocked field or else it will reinitialise thing.
  ConstructorInjected firstDependency = Mockito.mock(ConstructorInjected.class);
  thing = new ThingWithMixedDependencies(firstDependency);
  MockitoAnnotations.initMocks(this);
}

@Test
void checkDependencies() {
  assertThat(thing.getFirstDependency(), is(notNullValue()));
  assertThat(thing.getSecondDependency(), is(notNullValue()));
}

Yes, the @InjectMocks annotation makes Mockito EITHER do constructor injection, OR setter/field injection, but NEVER both. The rules around which will be chosen are quite complicated, which is one reason why I try to avoid using @InjectMocks whenever possible.

To summarise, Mockito FIRST chooses one constructor from among those that the class has, THEN analyses whether that constructor can be used for constructor injection. The one it chooses will always be the one with the greatest number of arguments. If there are several constructors with the same number of arguments, then it is undefined which one will be chosen.

Constructor injection will NOT be used if the type of one or more of the parameters of the CHOSEN constructor is a primitive type, or a final class or a private class. Even if there are other constructors that COULD be used.

If constructor injection is not used, or if the only constructor is the default constructor, then setter/field injection will be used instead. But setter/field injection is never used in conjunction with constructor injection.