Remove proxyTargetAware attribute from @⁠MockitoSpyBean

This commit removes the proxyTargetAware attribute from @⁠MockitoSpyBean
while keeping the underlying feature in tact (i.e., transparent
verification for spies created via @⁠MockitoSpyBean).

Closes gh-33775
This commit is contained in:
Sam Brannen
2024-10-23 16:23:21 +02:00
parent 20d21a8251
commit 5bf179b851
6 changed files with 32 additions and 89 deletions

View File

@@ -17,7 +17,6 @@
package org.springframework.test.context.bean.override.mockito;
import java.lang.reflect.Field;
import java.util.Objects;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.core.ResolvableType;
@@ -38,15 +37,12 @@ abstract class AbstractMockitoBeanOverrideHandler extends BeanOverrideHandler {
private final MockReset reset;
private final boolean proxyTargetAware;
protected AbstractMockitoBeanOverrideHandler(Field field, ResolvableType beanType, @Nullable String beanName,
BeanOverrideStrategy strategy, @Nullable MockReset reset, boolean proxyTargetAware) {
protected AbstractMockitoBeanOverrideHandler(Field field, ResolvableType beanType,
@Nullable String beanName, BeanOverrideStrategy strategy, @Nullable MockReset reset) {
super(field, beanType, beanName, strategy);
this.reset = (reset != null ? reset : MockReset.AFTER);
this.proxyTargetAware = proxyTargetAware;
}
@@ -58,14 +54,6 @@ abstract class AbstractMockitoBeanOverrideHandler extends BeanOverrideHandler {
return this.reset;
}
/**
* Return if AOP advised beans should be proxy target aware.
* @return if proxy target aware
*/
boolean isProxyTargetAware() {
return this.proxyTargetAware;
}
@Override
protected void trackOverrideInstance(Object mock, SingletonBeanRegistry trackingBeanRegistry) {
getMockitoBeans(trackingBeanRegistry).add(mock);
@@ -90,12 +78,12 @@ abstract class AbstractMockitoBeanOverrideHandler extends BeanOverrideHandler {
return true;
}
return (other instanceof AbstractMockitoBeanOverrideHandler that && super.equals(that) &&
(this.reset == that.reset) && (this.proxyTargetAware == that.proxyTargetAware));
this.reset == that.reset);
}
@Override
public int hashCode() {
return super.hashCode() + Objects.hash(this.reset, this.proxyTargetAware);
return super.hashCode() + this.reset.hashCode();
}
@Override
@@ -106,7 +94,6 @@ abstract class AbstractMockitoBeanOverrideHandler extends BeanOverrideHandler {
.append("beanName", getBeanName())
.append("strategy", getStrategy())
.append("reset", getReset())
.append("proxyTargetAware", isProxyTargetAware())
.toString();
}

View File

@@ -67,7 +67,7 @@ class MockitoBeanOverrideHandler extends AbstractMockitoBeanOverrideHandler {
BeanOverrideStrategy strategy, MockReset reset, Class<?>[] extraInterfaces, @Nullable Answers answers,
boolean serializable) {
super(field, typeToMock, beanName, strategy, reset, false);
super(field, typeToMock, beanName, strategy, reset);
Assert.notNull(typeToMock, "'typeToMock' must not be null");
this.extraInterfaces = asClassSet(extraInterfaces);
this.answers = (answers != null ? answers : Answers.RETURNS_DEFAULTS);

View File

@@ -22,8 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.mockito.Mockito;
import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.bean.override.BeanOverride;
@@ -87,17 +85,4 @@ public @interface MockitoSpyBean {
*/
MockReset reset() default MockReset.AFTER;
/**
* Indicates that Mockito methods such as {@link Mockito#verify(Object)
* verify(mock)} should use the {@code target} of AOP advised beans,
* rather than the proxy itself.
* <p>Defaults to {@code true}.
* <p>If set to {@code false} you may need to use the result of
* {@link org.springframework.test.util.AopTestUtils#getUltimateTargetObject(Object)
* AopTestUtils.getUltimateTargetObject(...)} when calling Mockito methods.
* @return {@code true} if the target of AOP advised beans is used, or
* {@code false} if the proxy is used directly
*/
boolean proxyTargetAware() default true;
}

View File

@@ -39,19 +39,24 @@ import org.springframework.util.StringUtils;
* @author Phillip Webb
* @author Simon Baslé
* @author Stephane Nicoll
* @author Sam Brannen
* @since 6.2
*/
class MockitoSpyBeanOverrideHandler extends AbstractMockitoBeanOverrideHandler {
private static final VerificationStartedListener verificationStartedListener =
new SpringAopBypassingVerificationStartedListener();
MockitoSpyBeanOverrideHandler(Field field, ResolvableType typeToSpy, MockitoSpyBean spyAnnotation) {
this(field, typeToSpy, (StringUtils.hasText(spyAnnotation.name()) ? spyAnnotation.name() : null),
spyAnnotation.reset(), spyAnnotation.proxyTargetAware());
spyAnnotation.reset());
}
MockitoSpyBeanOverrideHandler(Field field, ResolvableType typeToSpy, @Nullable String beanName,
MockReset reset, boolean proxyTargetAware) {
MockReset reset) {
super(field, typeToSpy, beanName, BeanOverrideStrategy.WRAP, reset, proxyTargetAware);
super(field, typeToSpy, beanName, BeanOverrideStrategy.WRAP, reset);
Assert.notNull(typeToSpy, "typeToSpy must not be null");
}
@@ -77,9 +82,7 @@ class MockitoSpyBeanOverrideHandler extends AbstractMockitoBeanOverrideHandler {
if (StringUtils.hasLength(name)) {
settings.name(name);
}
if (isProxyTargetAware()) {
settings.verificationStartedListeners(new SpringAopBypassingVerificationStartedListener());
}
settings.verificationStartedListeners(verificationStartedListener);
Class<?> toSpy;
if (Proxy.isProxyClass(instance.getClass())) {
settings.defaultAnswer(AdditionalAnswers.delegatesTo(instance));