Skip to content

Commit

Permalink
Avoid hard dependency on Spring AOP for mock resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
jhoeller committed Oct 23, 2024
1 parent c160e89 commit fe6d914
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,22 @@ protected Object createOverrideInstance(String beanName, @Nullable BeanDefinitio
return createSpy(beanName, existingBeanInstance);
}

@SuppressWarnings("unchecked")
private Object createSpy(String name, Object instance) {
Class<?> resolvedTypeToOverride = getBeanType().resolve();
Assert.notNull(resolvedTypeToOverride, "Failed to resolve type to override");
Assert.isInstanceOf(resolvedTypeToOverride, instance);
if (Mockito.mockingDetails(instance).isSpy()) {
return instance;
}

MockSettings settings = MockReset.withSettings(getReset());
if (StringUtils.hasLength(name)) {
settings.name(name);
}
settings.verificationStartedListeners(verificationStartedListener);
if (SpringMockResolver.aopAvailable) {
settings.verificationStartedListeners(verificationStartedListener);
}

Class<?> toSpy;
if (Proxy.isProxyClass(instance.getClass())) {
settings.defaultAnswer(AdditionalAnswers.delegatesTo(instance));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
* A {@link MockResolver} for testing Spring applications with Mockito.
Expand All @@ -31,30 +32,35 @@
*
* @author Sam Brannen
* @author Andy Wilkinson
* @author Juergen Hoeller
* @since 6.2
*/
public class SpringMockResolver implements MockResolver {

static final boolean aopAvailable = ClassUtils.isPresent(
"org.springframework.aop.framework.Advised", SpringMockResolver.class.getClassLoader());


@Override
public Object resolve(Object instance) {
return getUltimateTargetObject(instance);
if (aopAvailable) {
return getUltimateTargetObject(instance);
}
return instance;
}

/**
* This is a modified version of
* {@link org.springframework.test.util.AopTestUtils#getUltimateTargetObject(Object)
* AopTestUtils#getUltimateTargetObject()} which only checks static target
* sources.
* @param <T> the type of the target object
* AopTestUtils#getUltimateTargetObject()} which only checks static target sources.
* @param candidate the instance to check (potentially a Spring AOP proxy;
* never {@code null})
* @return the target object or the {@code candidate} (never {@code null})
* @throws IllegalStateException if an error occurs while unwrapping a proxy
* @see Advised#getTargetSource()
* @see TargetSource#isStatic()
*/
@SuppressWarnings("unchecked")
static <T> T getUltimateTargetObject(Object candidate) {
static Object getUltimateTargetObject(Object candidate) {
Assert.notNull(candidate, "Candidate must not be null");
try {
if (AopUtils.isAopProxy(candidate) && candidate instanceof Advised advised) {
Expand All @@ -70,7 +76,7 @@ static <T> T getUltimateTargetObject(Object candidate) {
catch (Throwable ex) {
throw new IllegalStateException("Failed to unwrap proxied object", ex);
}
return (T) candidate;
return candidate;
}

}

0 comments on commit fe6d914

Please sign in to comment.