Skip to content

Commit 027c5a0

Browse files
committed
Remove usage of Mockito's internals
Previously, we relied on Mockito's internals to bypass any Spring AOP proxy during verification of a spy. Thanks to a new API in Mockito, we can replace the use of Mockito's internals with a VerificationStartedListener. This listener changes Mockito's view of the mock to be the ultimate target of the AOP proxy, i.e. to be the actual Mockito-created spy, allowing Mockito's verification of the spy to proceed successfully. This above-described change will mean that we require a very up-to-date version of Mockito so the tests that verify our compatibility with 2.5 have been removed as we will no longer support it when using @MockBean or @SpyBean. Lastly, two tests have been updated to replace their usage of the internal MockUtil class with the equivalent public API calls. Closes gh-10352
1 parent ec4b804 commit 027c5a0

File tree

6 files changed

+30
-210
lines changed

6 files changed

+30
-210
lines changed

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoAopProxyTargetInterceptor.java

Lines changed: 0 additions & 133 deletions
This file was deleted.

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.TreeSet;
2828

2929
import org.springframework.aop.scope.ScopedProxyUtils;
30-
import org.springframework.aop.support.AopUtils;
3130
import org.springframework.beans.BeansException;
3231
import org.springframework.beans.PropertyValues;
3332
import org.springframework.beans.factory.BeanClassLoaderAware;
@@ -391,25 +390,13 @@ private void inject(Field field, Object target, String beanName,
391390
Assert.state(ReflectionUtils.getField(field, target) == null,
392391
() -> "The field " + field + " cannot have an existing value");
393392
Object bean = this.beanFactory.getBean(beanName, field.getType());
394-
if (definition.isProxyTargetAware() && isAopProxy(bean)) {
395-
MockitoAopProxyTargetInterceptor.applyTo(bean);
396-
}
397393
ReflectionUtils.setField(field, target, bean);
398394
}
399395
catch (Throwable ex) {
400396
throw new BeanCreationException("Could not inject field: " + field, ex);
401397
}
402398
}
403399

404-
private boolean isAopProxy(Object object) {
405-
try {
406-
return AopUtils.isAopProxy(object);
407-
}
408-
catch (Throwable ex) {
409-
return false;
410-
}
411-
}
412-
413400
@Override
414401
public int getOrder() {
415402
return Ordered.LOWEST_PRECEDENCE - 10;

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpyDefinition.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818

1919
import org.mockito.MockSettings;
2020
import org.mockito.Mockito;
21+
import org.mockito.listeners.VerificationStartedEvent;
22+
import org.mockito.listeners.VerificationStartedListener;
2123

2224
import org.springframework.core.ResolvableType;
2325
import org.springframework.core.style.ToStringCreator;
26+
import org.springframework.test.util.AopTestUtils;
2427
import org.springframework.util.Assert;
2528
import org.springframework.util.ObjectUtils;
2629
import org.springframework.util.StringUtils;
@@ -93,7 +96,25 @@ public <T> T createSpy(String name, Object instance) {
9396
}
9497
settings.spiedInstance(instance);
9598
settings.defaultAnswer(Mockito.CALLS_REAL_METHODS);
99+
if (this.isProxyTargetAware()) {
100+
settings.verificationStartedListeners(
101+
new SpringAopBypassingVerificationStartedListener());
102+
}
96103
return (T) Mockito.mock(instance.getClass(), settings);
97104
}
98105

106+
/**
107+
* A {@link VerificationStartedListener} that bypasses any proxy created by Spring AOP
108+
* when the verification of a spy starts.
109+
*/
110+
private static final class SpringAopBypassingVerificationStartedListener
111+
implements VerificationStartedListener {
112+
113+
@Override
114+
public void onVerificationStarted(VerificationStartedEvent event) {
115+
event.setMock(AopTestUtils.getUltimateTargetObject(event.getMock()));
116+
}
117+
118+
}
119+
99120
}

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/Mockito25Tests.java

Lines changed: 0 additions & 59 deletions
This file was deleted.

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegrationTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import org.junit.Test;
2020
import org.junit.runner.RunWith;
21-
import org.mockito.internal.util.MockUtil;
21+
import org.mockito.Mockito;
2222

2323
import org.springframework.beans.factory.annotation.Autowired;
2424
import org.springframework.boot.test.mock.mockito.example.ExampleGenericStringServiceCaller;
@@ -50,7 +50,8 @@ public class SpyBeanOnTestFieldForMultipleExistingBeansWithOnePrimaryIntegration
5050
@Test
5151
public void testSpying() throws Exception {
5252
assertThat(this.caller.sayGreeting()).isEqualTo("I say two");
53-
assertThat(MockUtil.getMockName(this.spy).toString()).isEqualTo("two");
53+
assertThat(Mockito.mockingDetails(this.spy).getMockCreationSettings()
54+
.getMockName().toString()).isEqualTo("two");
5455
verify(this.spy).greeting();
5556
}
5657

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
import org.junit.Test;
2020
import org.junit.runner.RunWith;
21-
import org.mockito.internal.util.MockUtil;
21+
import org.mockito.MockingDetails;
22+
import org.mockito.Mockito;
2223

2324
import org.springframework.boot.test.mock.mockito.example.SimpleExampleStringGenericService;
2425
import org.springframework.context.annotation.Bean;
@@ -42,8 +43,10 @@ public class SpyBeanWithNameOnTestFieldForMultipleExistingBeansTests {
4243

4344
@Test
4445
public void testSpying() throws Exception {
45-
assertThat(MockUtil.isSpy(this.spy)).isTrue();
46-
assertThat(MockUtil.getMockName(this.spy).toString()).isEqualTo("two");
46+
MockingDetails mockingDetails = Mockito.mockingDetails(this.spy);
47+
assertThat(mockingDetails.isMock()).isTrue();
48+
assertThat(mockingDetails.getMockCreationSettings().getMockName().toString())
49+
.isEqualTo("two");
4750
}
4851

4952
@Configuration

0 commit comments

Comments
 (0)