Mockito injection not working for constructor AND setter mocks together

落爺英雄遲暮 提交于 2019-12-04 06:33:30

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.

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()));
}

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.

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