Mocks are not injected in fields that are Spring AOP proxies. To solve it you can modify PropertyAndSetterInjection:
public boolean processInjection(Field injectMocksField, Object injectMocksFieldOwner, Set<Object> mockCandidates) {
// Set<Object> mocksToBeInjected = new HashSet<Object>(mockCandidates);
FieldInitializationReport report = initializeInjectMocksField(injectMocksField, injectMocksFieldOwner);
// for each field in the class hierarchy
boolean injectionOccurred = false;
Class<?> fieldClass = report.fieldClass();
Object fieldInstanceNeedingInjection = report.fieldInstance();
// Unwrap proxy to allow field injection
fieldInstanceNeedingInjection = unwrapProxy(fieldInstanceNeedingInjection);
fieldClass = fieldInstanceNeedingInjection.getClass();
while (fieldClass != Object.class) {
injectionOccurred |= injectMockCandidates(fieldClass, newMockSafeHashSet(mockCandidates), fieldInstanceNeedingInjection);
fieldClass = fieldClass.getSuperclass();
}
return injectionOccurred;
}
public static Object unwrapProxy(Object bean) {
if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
Advised advised = (Advised) bean;
try {
bean = advised.getTargetSource().getTarget();
} catch (Exception e) {
LOG.error("Exception unwrapping proxy object", e);
}
}
return bean;
}
Hi,
Thanks for providing a solution however we won't include Spring specific code in mockito.
This seems to be a problem quite specific to how is the test crafted. This is probably wrong to create an object then inject mocks (then overriding exisiting wired dependencies), a better approach would probably be to let spring wire the mocks.
FYI, I've run into this too and have filed an upstream issue with Spring:
I have also run into this issue, and while it is rare, rewriting the test to no use @InjectMocks does make the configuration quite a bit more verbose. It appears like the fundamental flaw in the injection filtering is that there is an assumption that there is a one-to-one between a field and a getter/setter pair. When a proxy is in usage, particularly a CGLIB proxy, this is obviously not the case.
A solution could be provided that did not couple to Spring, but I believe it would require adjusting the filtering strategy for setter injection to find candidate injectables but setter method declaration, not field declaration.
You can use the new Spring Boot feature - http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans
Most helpful comment
You can use the new Spring Boot feature - http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans