Upgrade to Mockito 2

Closes gh-7770
This commit is contained in:
Stephane Nicoll
2017-01-04 19:52:02 +01:00
parent ad2ff27208
commit c28ff4314c
14 changed files with 205 additions and 65 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -108,7 +108,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
if (mode instanceof MockAwareVerificationMode) {
MockAwareVerificationMode mockAwareMode = (MockAwareVerificationMode) mode;
if (mockAwareMode.getMock() == source) {
mode = new MockAwareVerificationMode(target, mockAwareMode);
mode = SpringBootMockUtil.createMockAwareVerificationMode(
target, mockAwareMode);
}
}
resetVerificationStarted(mode);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,17 +16,23 @@
package org.springframework.boot.test.mock.mockito;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.mockito.ArgumentMatcher;
import org.hamcrest.Matcher;
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.util.MockUtil;
import org.mockito.internal.verification.MockAwareVerificationMode;
import org.mockito.mock.MockCreationSettings;
import org.mockito.verification.VerificationMode;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -35,18 +41,19 @@ import org.springframework.util.ReflectionUtils;
* and 2.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
final class SpringBootMockUtil {
private static final MockUtilAdapter adapter;
static {
if (ClassUtils.isPresent("org.mockito.quality.MockitoHint",
if (ClassUtils.isPresent("org.mockito.ReturnValues",
SpringBootMockUtil.class.getClassLoader())) {
adapter = new Mockito2MockUtilAdapter();
adapter = new Mockito1MockUtilAdapter();
}
else {
adapter = new Mockito1MockUtilAdapter();
adapter = new Mockito2MockUtilAdapter();
}
}
@@ -67,6 +74,11 @@ final class SpringBootMockUtil {
adapter.reportMatchers(storage, matchers);
}
static MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode) {
return adapter.createMockAwareVerificationMode(mock, mode);
}
private interface MockUtilAdapter {
MockCreationSettings<?> getMockSettings(Object mock);
@@ -76,15 +88,53 @@ final class SpringBootMockUtil {
void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers);
MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode);
}
private static class Mockito1MockUtilAdapter implements MockUtilAdapter {
private static final MockingProgress mockingProgress = new ThreadSafeMockingProgress();
private final MockUtil mockUtil = BeanUtils.instantiate(MockUtil.class);
private final Method getMockSettingsMethod = ReflectionUtils
.findMethod(MockUtil.class, "getMockSettings", Object.class);
private static final MockingProgress mockingProgress =
createThreadSafeMockingProgress();
private final Method reportMatcherMethod = ReflectionUtils.findMethod(
ArgumentMatcherStorage.class, "reportMatcher", Matcher.class);
private static final Constructor<MockAwareVerificationMode> mockAwareVerificationModeConstructor =
getMockAwareVerificationModeConstructor();
private static MockingProgress createThreadSafeMockingProgress() {
try {
Class<?> target = ClassUtils.forName(
"org.mockito.internal.progress.ThreadSafeMockingProgress",
SpringBootMockUtil.class.getClassLoader());
return (MockingProgress) BeanUtils.instantiateClass(target);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(ex);
}
}
private static Constructor<MockAwareVerificationMode> getMockAwareVerificationModeConstructor() {
try {
return MockAwareVerificationMode.class.getConstructor(Object.class,
VerificationMode.class);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException(ex);
}
}
@Override
public MockCreationSettings<?> getMockSettings(Object mock) {
return new MockUtil().getMockSettings(mock);
return (MockCreationSettings<?>) ReflectionUtils
.invokeMethod(this.getMockSettingsMethod, this.mockUtil, mock);
}
@Override
@@ -96,44 +146,83 @@ final class SpringBootMockUtil {
public void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers) {
for (LocalizedMatcher matcher : matchers) {
storage.reportMatcher(matcher);
ReflectionUtils.invokeMethod(this.reportMatcherMethod, storage, matcher);
}
}
@Override
public MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode) {
return BeanUtils.instantiateClass(mockAwareVerificationModeConstructor, mock,
mode);
}
}
private static class Mockito2MockUtilAdapter implements MockUtilAdapter {
private final Method getMockSettingsMethod = ReflectionUtils
.findMethod(MockUtil.class, "getMockSettings", Object.class);
private static final Constructor<MockAwareVerificationMode> mockAwareVerificationModeConstructor;
private static final boolean mockAwareVerificationModeLegacy;
private final Method mockingProgressMethod = ReflectionUtils
.findMethod(ThreadSafeMockingProgress.class, "mockingProgress");
private final Method reportMatcherMethod = ReflectionUtils.findMethod(
ArgumentMatcherStorage.class, "reportMatcher", ArgumentMatcher.class);
private final Method getMatcherMethod = ReflectionUtils
.findMethod(LocalizedMatcher.class, "getMatcher");
static {
Constructor<MockAwareVerificationMode> c = getMockAwareVerificationModeConstructor();
if (c != null) {
mockAwareVerificationModeConstructor = c;
mockAwareVerificationModeLegacy = false;
}
else {
mockAwareVerificationModeConstructor = getMockAwareVerificationModeLegacyConstructor();
mockAwareVerificationModeLegacy = true;
}
}
@Override
public MockCreationSettings<?> getMockSettings(Object mock) {
return (MockCreationSettings<?>) ReflectionUtils
.invokeMethod(this.getMockSettingsMethod, null, mock);
return MockUtil.getMockSettings(mock);
}
@Override
public MockingProgress mockingProgress() {
return (MockingProgress) ReflectionUtils
.invokeMethod(this.mockingProgressMethod, null);
return ThreadSafeMockingProgress.mockingProgress();
}
@Override
public void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers) {
for (LocalizedMatcher matcher : matchers) {
ReflectionUtils.invokeMethod(this.reportMatcherMethod, storage,
ReflectionUtils.invokeMethod(this.getMatcherMethod, matcher));
storage.reportMatcher(matcher.getMatcher());
}
}
@Override
public MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode) {
if (mockAwareVerificationModeLegacy) {
return BeanUtils.instantiateClass(mockAwareVerificationModeConstructor,
mock, mode);
}
else {
return BeanUtils.instantiateClass(mockAwareVerificationModeConstructor,
mock, mode, Collections.emptySet());
}
}
private static Constructor<MockAwareVerificationMode> getMockAwareVerificationModeLegacyConstructor() {
try {
return MockAwareVerificationMode.class.getConstructor(Object.class,
VerificationMode.class);
}
catch (NoSuchMethodException ex) {
return null;
}
}
private static Constructor<MockAwareVerificationMode> getMockAwareVerificationModeConstructor() {
try {
return MockAwareVerificationMode.class.getConstructor(Object.class,
VerificationMode.class, Set.class);
}
catch (NoSuchMethodException ex) {
return null;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.test.mock.mockito;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.springframework.boot.junit.runner.classpath.ClassPathOverrides;
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for compatibility with Mockito 1.10
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
@RunWith(ModifiedClassPathRunner.class)
@ClassPathOverrides("org.mockito:mockito-core:1.10.19")
public class Mockito110Tests {
@Test
public void spyBeanWithAopProxyTestsWithMockito1() {
runTests(SpyBeanWithAopProxyTests.class);
}
private void runTests(Class<?> testClass) {
Result result = new JUnitCore().run(testClass);
assertThat(result.getFailureCount()).isEqualTo(0);
assertThat(result.getRunCount()).isGreaterThan(0);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ public class SpyBeanOnTestFieldForMultipleExistingBeansIntegrationTests {
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say two");
assertThat(new MockUtil().getMockName(this.spy).toString()).isEqualTo("two");
assertThat(MockUtil.getMockName(this.spy).toString()).isEqualTo("two");
verify(this.spy).greeting();
}