From fe6d9145e553f9224f229365414db404cc823f68 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 23 Oct 2024 21:26:06 +0200 Subject: [PATCH] Avoid hard dependency on Spring AOP for mock resolution Closes gh-33774 --- .../MockitoSpyBeanOverrideHandler.java | 7 +++++-- .../override/mockito/SpringMockResolver.java | 20 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandler.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandler.java index 6160b98cc962..0ebe08283d2c 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandler.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandler.java @@ -70,7 +70,6 @@ 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"); @@ -78,11 +77,15 @@ private Object createSpy(String name, Object 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)); diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/SpringMockResolver.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/SpringMockResolver.java index 36cf0094ecbf..75fef142a7c3 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/SpringMockResolver.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/SpringMockResolver.java @@ -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. @@ -31,21 +32,27 @@ * * @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 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}) @@ -53,8 +60,7 @@ public Object resolve(Object instance) { * @see Advised#getTargetSource() * @see TargetSource#isStatic() */ - @SuppressWarnings("unchecked") - static 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) { @@ -70,7 +76,7 @@ static T getUltimateTargetObject(Object candidate) { catch (Throwable ex) { throw new IllegalStateException("Failed to unwrap proxied object", ex); } - return (T) candidate; + return candidate; } }