Browse Source

Avoid hard dependency on Spring AOP for mock resolution

Closes gh-33774
pull/33793/head
Juergen Hoeller 1 year ago
parent
commit
fe6d9145e5
  1. 5
      spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandler.java
  2. 18
      spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/SpringMockResolver.java

5
spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandler.java

@ -70,7 +70,6 @@ class MockitoSpyBeanOverrideHandler extends AbstractMockitoBeanOverrideHandler {
return createSpy(beanName, existingBeanInstance); return createSpy(beanName, existingBeanInstance);
} }
@SuppressWarnings("unchecked")
private Object createSpy(String name, Object instance) { private Object createSpy(String name, Object instance) {
Class<?> resolvedTypeToOverride = getBeanType().resolve(); Class<?> resolvedTypeToOverride = getBeanType().resolve();
Assert.notNull(resolvedTypeToOverride, "Failed to resolve type to override"); Assert.notNull(resolvedTypeToOverride, "Failed to resolve type to override");
@ -78,11 +77,15 @@ class MockitoSpyBeanOverrideHandler extends AbstractMockitoBeanOverrideHandler {
if (Mockito.mockingDetails(instance).isSpy()) { if (Mockito.mockingDetails(instance).isSpy()) {
return instance; return instance;
} }
MockSettings settings = MockReset.withSettings(getReset()); MockSettings settings = MockReset.withSettings(getReset());
if (StringUtils.hasLength(name)) { if (StringUtils.hasLength(name)) {
settings.name(name); settings.name(name);
} }
if (SpringMockResolver.aopAvailable) {
settings.verificationStartedListeners(verificationStartedListener); settings.verificationStartedListeners(verificationStartedListener);
}
Class<?> toSpy; Class<?> toSpy;
if (Proxy.isProxyClass(instance.getClass())) { if (Proxy.isProxyClass(instance.getClass())) {
settings.defaultAnswer(AdditionalAnswers.delegatesTo(instance)); settings.defaultAnswer(AdditionalAnswers.delegatesTo(instance));

18
spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/SpringMockResolver.java

@ -22,6 +22,7 @@ import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* A {@link MockResolver} for testing Spring applications with Mockito. * A {@link MockResolver} for testing Spring applications with Mockito.
@ -31,21 +32,27 @@ import org.springframework.util.Assert;
* *
* @author Sam Brannen * @author Sam Brannen
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Juergen Hoeller
* @since 6.2 * @since 6.2
*/ */
public class SpringMockResolver implements MockResolver { public class SpringMockResolver implements MockResolver {
static final boolean aopAvailable = ClassUtils.isPresent(
"org.springframework.aop.framework.Advised", SpringMockResolver.class.getClassLoader());
@Override @Override
public Object resolve(Object instance) { public Object resolve(Object instance) {
if (aopAvailable) {
return getUltimateTargetObject(instance); return getUltimateTargetObject(instance);
} }
return instance;
}
/** /**
* This is a modified version of * This is a modified version of
* {@link org.springframework.test.util.AopTestUtils#getUltimateTargetObject(Object) * {@link org.springframework.test.util.AopTestUtils#getUltimateTargetObject(Object)
* AopTestUtils#getUltimateTargetObject()} which only checks static target * AopTestUtils#getUltimateTargetObject()} which only checks static target sources.
* sources.
* @param <T> the type of the target object
* @param candidate the instance to check (potentially a Spring AOP proxy; * @param candidate the instance to check (potentially a Spring AOP proxy;
* never {@code null}) * never {@code null})
* @return the target object or the {@code candidate} (never {@code null}) * @return the target object or the {@code candidate} (never {@code null})
@ -53,8 +60,7 @@ public class SpringMockResolver implements MockResolver {
* @see Advised#getTargetSource() * @see Advised#getTargetSource()
* @see TargetSource#isStatic() * @see TargetSource#isStatic()
*/ */
@SuppressWarnings("unchecked") static Object getUltimateTargetObject(Object candidate) {
static <T> T getUltimateTargetObject(Object candidate) {
Assert.notNull(candidate, "Candidate must not be null"); Assert.notNull(candidate, "Candidate must not be null");
try { try {
if (AopUtils.isAopProxy(candidate) && candidate instanceof Advised advised) { if (AopUtils.isAopProxy(candidate) && candidate instanceof Advised advised) {
@ -70,7 +76,7 @@ public class SpringMockResolver implements MockResolver {
catch (Throwable ex) { catch (Throwable ex) {
throw new IllegalStateException("Failed to unwrap proxied object", ex); throw new IllegalStateException("Failed to unwrap proxied object", ex);
} }
return (T) candidate; return candidate;
} }
} }

Loading…
Cancel
Save