Reputation: 7851
in order to mock some @Transactional
annotated classes, I must disable Springs` aop proxy creation for them.
How can I configure my spring boot application to exclude any proxy creation for specific spring beans at all or how can I remove all advices for this bean?
Subclassing e.g. InfrastructureAdvisorAutoProxyCreator was already suggested, but throws an Class name [null] is not a known auto-proxy creator class
error. It seems it's statically initialized in org.springframework.aop.config.AopConfigUtils
.
Upvotes: 4
Views: 4300
Reputation: 7851
Spring now offers a solution to this by providing AopTestUtils
, e.g.
AopTestUtils.getUltimateTargetObject(bean)
My previous workaround unwrapped the proxy using Springs' AopUtils
:
@SuppressWarnings("unchecked")
public <T> T unwrapProxy(T bean) {
if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
Advised advised = (Advised) bean;
try {
bean = (T) advised.getTargetSource().getTarget();
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
return bean;
}
Upvotes: 5
Reputation: 14552
Not the answer to you original question. But I think you can use @InjectMocks
of mockito as a solution here. It should work even if the class marked as @Transactional
. Here are some questions on topic. From docs,
@InjectMock Mark a field on which injection should be performed.
Allows shorthand mock and spy injection. Minimizes repetitive mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.
Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. Note: If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won't happen. In these cases, you will have to satisfy dependencies yourself.
Property setter injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the property name and the mock name.
Note 1: If you have properties with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.
Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Field injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the field name and the mock name.
Note 1: If you have fields with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.
Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Upvotes: 1