Fix Mockito 2 support
See gh-7770
This commit is contained in:
@@ -53,7 +53,7 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
|
||||
MockitoAopProxyTargetInterceptor(Object source, Object target) throws Exception {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.verification = new Verification();
|
||||
this.verification = new Verification(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,7 +89,11 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final MockingProgress progress = MockitoApi.get().mockingProgress();
|
||||
private final MockingProgress progress;
|
||||
|
||||
Verification(Object target) {
|
||||
this.progress = MockitoApi.get().mockingProgress(target);
|
||||
}
|
||||
|
||||
public boolean isVerifying() {
|
||||
synchronized (this.monitor) {
|
||||
@@ -121,7 +125,7 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
|
||||
private void resetVerificationStarted(VerificationMode mode) {
|
||||
ArgumentMatcherStorage storage = this.progress.getArgumentMatcherStorage();
|
||||
List<LocalizedMatcher> matchers = storage.pullLocalizedMatchers();
|
||||
MockitoApi.get().mockingProgress().verificationStarted(mode);
|
||||
this.progress.verificationStarted(mode);
|
||||
MockitoApi.get().reportMatchers(storage, matchers);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,16 +17,19 @@
|
||||
package org.springframework.boot.test.mock.mockito;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.internal.InternalMockHandler;
|
||||
import org.mockito.internal.matchers.LocalizedMatcher;
|
||||
import org.mockito.internal.progress.ArgumentMatcherStorage;
|
||||
import org.mockito.internal.progress.MockingProgress;
|
||||
import org.mockito.internal.progress.ThreadSafeMockingProgress;
|
||||
import org.mockito.internal.stubbing.InvocationContainer;
|
||||
import org.mockito.internal.util.MockUtil;
|
||||
import org.mockito.internal.verification.MockAwareVerificationMode;
|
||||
import org.mockito.mock.MockCreationSettings;
|
||||
@@ -57,9 +60,10 @@ abstract class MockitoApi {
|
||||
|
||||
/**
|
||||
* Return the mocking progress for the current thread.
|
||||
* @param mock the mock object
|
||||
* @return the current mocking progress
|
||||
*/
|
||||
public abstract MockingProgress mockingProgress();
|
||||
public abstract MockingProgress mockingProgress(Object mock);
|
||||
|
||||
/**
|
||||
* Set report matchers to the given storage.
|
||||
@@ -90,11 +94,10 @@ abstract class MockitoApi {
|
||||
* @return the API version
|
||||
*/
|
||||
private static MockitoApi createApi() {
|
||||
if (!ClassUtils.isPresent("org.mockito.ReturnValues",
|
||||
MockitoApi.class.getClassLoader())) {
|
||||
return new Mockito2Api();
|
||||
if (ClassUtils.isPresent("org.mockito.ReturnValues", null)) {
|
||||
return new Mockito1Api();
|
||||
}
|
||||
return new Mockito1Api();
|
||||
return new Mockito2Api();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,6 +108,74 @@ abstract class MockitoApi {
|
||||
return api;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MockitoApi} for Mockito 1.0.
|
||||
*/
|
||||
private static class Mockito1Api extends MockitoApi {
|
||||
|
||||
private final MockUtil mockUtil;
|
||||
|
||||
private final Method getMockSettingsMethod;
|
||||
|
||||
private final Method getMockHandlerMethod;
|
||||
|
||||
private Method reportMatcherMethod;
|
||||
|
||||
private Constructor<MockAwareVerificationMode> mockAwareVerificationModeConstructor;
|
||||
|
||||
Mockito1Api() {
|
||||
this.mockUtil = BeanUtils.instantiateClass(MockUtil.class);
|
||||
this.getMockSettingsMethod = ReflectionUtils.findMethod(MockUtil.class,
|
||||
"getMockSettings", Object.class);
|
||||
this.getMockHandlerMethod = ReflectionUtils.findMethod(MockUtil.class,
|
||||
"getMockHandler", Object.class);
|
||||
this.reportMatcherMethod = ReflectionUtils.findMethod(
|
||||
ArgumentMatcherStorage.class, "reportMatcher", Matcher.class);
|
||||
this.mockAwareVerificationModeConstructor = ClassUtils
|
||||
.getConstructorIfAvailable(MockAwareVerificationMode.class,
|
||||
Object.class, VerificationMode.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockCreationSettings<?> getMockSettings(Object mock) {
|
||||
return (MockCreationSettings<?>) ReflectionUtils
|
||||
.invokeMethod(this.getMockSettingsMethod, this.mockUtil, mock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockingProgress mockingProgress(Object mock) {
|
||||
InternalMockHandler<?> handler = (InternalMockHandler<?>) ReflectionUtils
|
||||
.invokeMethod(this.getMockHandlerMethod, this.mockUtil, mock);
|
||||
InvocationContainer container = handler.getInvocationContainer();
|
||||
Field field = ReflectionUtils.findField(container.getClass(),
|
||||
"mockingProgress");
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return (MockingProgress) ReflectionUtils.getField(field, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportMatchers(ArgumentMatcherStorage storage,
|
||||
List<LocalizedMatcher> matchers) {
|
||||
for (LocalizedMatcher matcher : matchers) {
|
||||
ReflectionUtils.invokeMethod(this.reportMatcherMethod, storage, matcher);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
|
||||
VerificationMode mode) {
|
||||
return BeanUtils.instantiateClass(this.mockAwareVerificationModeConstructor,
|
||||
mock, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Answer<Object> getAnswer(Answers answer) {
|
||||
return answer.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MockitoApi} for Mockito 2.0.
|
||||
*/
|
||||
@@ -116,7 +187,7 @@ abstract class MockitoApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockingProgress mockingProgress() {
|
||||
public MockingProgress mockingProgress(Object mock) {
|
||||
return ThreadSafeMockingProgress.mockingProgress();
|
||||
}
|
||||
|
||||
@@ -153,68 +224,4 @@ abstract class MockitoApi {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MockitoApi} for Mockito 1.0.
|
||||
*/
|
||||
private static class Mockito1Api extends MockitoApi {
|
||||
|
||||
private final MockUtil mockUtil;
|
||||
|
||||
private final Method getMockSettingsMethod;
|
||||
|
||||
private final MockingProgress mockingProgress;
|
||||
|
||||
private Method reportMatcherMethod;
|
||||
|
||||
private Constructor<MockAwareVerificationMode> mockAwareVerificationModeConstructor;
|
||||
|
||||
Mockito1Api() {
|
||||
this.mockUtil = BeanUtils.instantiateClass(MockUtil.class);
|
||||
this.getMockSettingsMethod = ReflectionUtils.findMethod(MockUtil.class,
|
||||
"getMockSettings", Object.class);
|
||||
this.mockingProgress = (MockingProgress) BeanUtils
|
||||
.instantiateClass(ClassUtils.resolveClassName(
|
||||
"org.mockito.internal.progress.ThreadSafeMockingProgress",
|
||||
MockitoApi.class.getClassLoader()));
|
||||
this.reportMatcherMethod = ReflectionUtils.findMethod(
|
||||
ArgumentMatcherStorage.class, "reportMatcher", Matcher.class);
|
||||
this.mockAwareVerificationModeConstructor = ClassUtils
|
||||
.getConstructorIfAvailable(MockAwareVerificationMode.class,
|
||||
Object.class, VerificationMode.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockCreationSettings<?> getMockSettings(Object mock) {
|
||||
return (MockCreationSettings<?>) ReflectionUtils
|
||||
.invokeMethod(this.getMockSettingsMethod, this.mockUtil, mock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockingProgress mockingProgress() {
|
||||
return this.mockingProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportMatchers(ArgumentMatcherStorage storage,
|
||||
List<LocalizedMatcher> matchers) {
|
||||
for (LocalizedMatcher matcher : matchers) {
|
||||
ReflectionUtils.invokeMethod(this.reportMatcherMethod, storage, matcher);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
|
||||
VerificationMode mode) {
|
||||
return BeanUtils.instantiateClass(this.mockAwareVerificationModeConstructor,
|
||||
mock, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Answer<Object> getAnswer(Answers answer) {
|
||||
return answer.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.JUnitCore;
|
||||
import org.junit.runner.Result;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.Failure;
|
||||
|
||||
import org.springframework.boot.junit.runner.classpath.ClassPathOverrides;
|
||||
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
|
||||
@@ -43,6 +44,9 @@ public class Mockito110Tests {
|
||||
|
||||
private void runTests(Class<?> testClass) {
|
||||
Result result = new JUnitCore().run(testClass);
|
||||
for (Failure failure : result.getFailures()) {
|
||||
System.err.println(failure.getTrace());
|
||||
}
|
||||
assertThat(result.getFailureCount()).isEqualTo(0);
|
||||
assertThat(result.getRunCount()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.JUnitCore;
|
||||
import org.junit.runner.Result;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.Failure;
|
||||
|
||||
import org.springframework.boot.junit.runner.classpath.ClassPathOverrides;
|
||||
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
|
||||
@@ -47,6 +48,9 @@ public class Mockito21Tests {
|
||||
|
||||
private void runTests(Class<?> testClass) {
|
||||
Result result = new JUnitCore().run(testClass);
|
||||
for (Failure failure : result.getFailures()) {
|
||||
System.err.println(failure.getTrace());
|
||||
}
|
||||
assertThat(result.getFailureCount()).isEqualTo(0);
|
||||
assertThat(result.getRunCount()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.JUnitCore;
|
||||
import org.junit.runner.Result;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runner.notification.Failure;
|
||||
|
||||
import org.springframework.boot.junit.runner.classpath.ClassPathOverrides;
|
||||
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
|
||||
@@ -47,6 +48,9 @@ public class Mockito22Tests {
|
||||
|
||||
private void runTests(Class<?> testClass) {
|
||||
Result result = new JUnitCore().run(testClass);
|
||||
for (Failure failure : result.getFailures()) {
|
||||
System.err.println(failure.getTrace());
|
||||
}
|
||||
assertThat(result.getFailureCount()).isEqualTo(0);
|
||||
assertThat(result.getRunCount()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.boot.test.mock.mockito;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
@@ -32,10 +34,10 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@@ -58,8 +60,32 @@ public class SpyBeanWithAopProxyTests {
|
||||
Long d2 = this.dateService.getDate(false);
|
||||
assertThat(d1).isEqualTo(d2);
|
||||
verify(this.dateService, times(1)).getDate(false);
|
||||
verify(this.dateService, times(1)).getDate(eq(false));
|
||||
verify(this.dateService, times(1)).getDate(anyBoolean());
|
||||
verify(this.dateService, times(1)).getDate(matchesFalse());
|
||||
verify(this.dateService, times(1)).getDate(matchesAnyBoolean());
|
||||
}
|
||||
|
||||
private boolean matchesFalse() {
|
||||
if (isTestingMockito1()) {
|
||||
Method method = ReflectionUtils.findMethod(
|
||||
ClassUtils.resolveClassName("org.mockito.Matchers", null), "eq",
|
||||
Boolean.TYPE);
|
||||
return (boolean) ReflectionUtils.invokeMethod(method, null, false);
|
||||
}
|
||||
return ArgumentMatchers.eq(false);
|
||||
}
|
||||
|
||||
private boolean matchesAnyBoolean() {
|
||||
if (isTestingMockito1()) {
|
||||
Method method = ReflectionUtils.findMethod(
|
||||
ClassUtils.resolveClassName("org.mockito.Matchers", null),
|
||||
"anyBoolean");
|
||||
return (boolean) ReflectionUtils.invokeMethod(method, null);
|
||||
}
|
||||
return ArgumentMatchers.anyBoolean();
|
||||
}
|
||||
|
||||
private boolean isTestingMockito1() {
|
||||
return ClassUtils.isPresent("org.mockito.ReturnValues", null);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
Reference in New Issue
Block a user