Polish Mockito 2 support

gh-7770
pull/2430/merge
Phillip Webb 8 years ago
parent 0cc313f224
commit 9048c97572

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>

@ -24,7 +24,6 @@ import java.util.Set;
import org.mockito.Answers;
import org.mockito.MockSettings;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.core.ResolvableType;
import org.springframework.core.style.ToStringCreator;
@ -149,19 +148,11 @@ class MockDefinition extends Definition {
if (!this.extraInterfaces.isEmpty()) {
settings.extraInterfaces(this.extraInterfaces.toArray(new Class<?>[] {}));
}
settings.defaultAnswer(getAnswer(this.answer));
settings.defaultAnswer(MockitoApi.get().getAnswer(this.answer));
if (this.serializable) {
settings.serializable();
}
return (T) Mockito.mock(this.typeToMock.resolve(), settings);
}
private Answer<?> getAnswer(Answers answer) {
if (Answer.class.isInstance(answer)) {
// With Mockito 2.0 we can directly cast the answer
return (Answer<?>) ((Object) answer);
}
return answer.get();
}
}

@ -105,7 +105,7 @@ public enum MockReset {
MockReset reset = MockReset.NONE;
if (ClassUtils.isPresent("org.mockito.internal.util.MockUtil", null)) {
if (Mockito.mockingDetails(mock).isMock()) {
MockCreationSettings settings = SpringBootMockUtil.getMockSettings(mock);
MockCreationSettings settings = MockitoApi.get().getMockSettings(mock);
List listeners = settings.getInvocationListeners();
for (Object listener : listeners) {
if (listener instanceof ResetInvocationListener) {

@ -24,6 +24,7 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.mockito.internal.matchers.LocalizedMatcher;
import org.mockito.internal.progress.ArgumentMatcherStorage;
import org.mockito.internal.progress.MockingProgress;
import org.mockito.internal.verification.MockAwareVerificationMode;
import org.mockito.verification.VerificationMode;
@ -88,10 +89,11 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
private final Object monitor = new Object();
private final MockingProgress progress = MockitoApi.get().mockingProgress();
public boolean isVerifying() {
synchronized (this.monitor) {
VerificationMode mode = SpringBootMockUtil.mockingProgress()
.pullVerificationMode();
VerificationMode mode = this.progress.pullVerificationMode();
if (mode != null) {
resetVerificationStarted(mode);
return true;
@ -102,13 +104,12 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
public void replaceVerifyMock(Object source, Object target) {
synchronized (this.monitor) {
VerificationMode mode = SpringBootMockUtil.mockingProgress()
.pullVerificationMode();
VerificationMode mode = this.progress.pullVerificationMode();
if (mode != null) {
if (mode instanceof MockAwareVerificationMode) {
MockAwareVerificationMode mockAwareMode = (MockAwareVerificationMode) mode;
if (mockAwareMode.getMock() == source) {
mode = SpringBootMockUtil.createMockAwareVerificationMode(
mode = MockitoApi.get().createMockAwareVerificationMode(
target, mockAwareMode);
}
}
@ -118,11 +119,10 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
}
private void resetVerificationStarted(VerificationMode mode) {
ArgumentMatcherStorage storage = SpringBootMockUtil.mockingProgress()
.getArgumentMatcherStorage();
ArgumentMatcherStorage storage = this.progress.getArgumentMatcherStorage();
List<LocalizedMatcher> matchers = storage.pullLocalizedMatchers();
SpringBootMockUtil.mockingProgress().verificationStarted(mode);
SpringBootMockUtil.reportMatchers(storage, matchers);
MockitoApi.get().mockingProgress().verificationStarted(mode);
MockitoApi.get().reportMatchers(storage, matchers);
}
}

@ -0,0 +1,240 @@
/*
* Copyright 2012-2016 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 java.lang.reflect.Constructor;
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.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.stubbing.Answer;
import org.mockito.verification.VerificationMode;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* A facade for Mockito APIs that have changed between Mockito 1 and Mockito 2.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Phillip Webb
*/
abstract class MockitoApi {
private static final MockitoApi api = createApi();
/**
* Return mock settings for the given mock object.
* @param mock the mock object
* @return the mock creation settings
*/
public abstract MockCreationSettings<?> getMockSettings(Object mock);
/**
* Return the mocking progress for the current thread.
* @return the current mocking progress
*/
public abstract MockingProgress mockingProgress();
/**
* Set report matchers to the given storage.
* @param storage the storage to use
* @param matchers the matchers to set
*/
public abstract void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers);
/**
* Create a new {@link MockAwareVerificationMode} instance.
* @param mock the source mock
* @param mode the verification mode
* @return a new {@link MockAwareVerificationMode} instance
*/
public abstract MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode);
/**
* Return the {@link Answer} for a given {@link Answers} value.
* @param answer the source answers
* @return the answer
*/
public abstract Answer<Object> getAnswer(Answers answer);
/**
* Factory to create the appropriate API version.
* @return the API version
*/
private static MockitoApi createApi() {
if (!ClassUtils.isPresent("org.mockito.ReturnValues",
MockitoApi.class.getClassLoader())) {
return new Mockito2Api();
}
return new Mockito1Api();
}
/**
* Get the API for the running mockito version.
* @return the API
*/
public static MockitoApi get() {
return api;
}
/**
* {@link MockitoApi} for Mockito 2.0.
*/
private static class Mockito2Api extends MockitoApi {
@Override
public MockCreationSettings<?> getMockSettings(Object mock) {
return MockUtil.getMockSettings(mock);
}
@Override
public MockingProgress mockingProgress() {
return ThreadSafeMockingProgress.mockingProgress();
}
@Override
public void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers) {
for (LocalizedMatcher matcher : matchers) {
storage.reportMatcher(matcher.getMatcher());
}
}
@Override
public MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode) {
try {
return new MockAwareVerificationMode(mock, mode, Collections.emptySet());
}
catch (NoSuchMethodError ex) {
// Earlier versions of 2.x did not have the collection parameter
Constructor<MockAwareVerificationMode> constructor = ClassUtils
.getConstructorIfAvailable(MockAwareVerificationMode.class,
Object.class, VerificationMode.class);
if (constructor == null) {
throw ex;
}
return BeanUtils.instantiateClass(constructor, mock, mode);
}
}
@Override
public Answer<Object> getAnswer(Answers answer) {
return answer;
}
}
/**
* {@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 = findMockSettingsMethod();
this.mockingProgress = (MockingProgress) BeanUtils
.instantiateClass(ClassUtils.resolveClassName(
"org.mockito.internal.progress.ThreadSafeMockingProgress",
MockitoApi.class.getClassLoader()));
this.reportMatcherMethod = findReportMatcherMethod();
this.mockAwareVerificationModeConstructor = findMockAwareVerificationModeConstructor();
}
private Method findMockSettingsMethod() {
Method method = ReflectionUtils.findMethod(MockUtil.class, "getMockSettings",
Object.class);
Assert.state(method != null, "Unable to find getMockSettings method");
return method;
}
private Method findReportMatcherMethod() {
Method method = ReflectionUtils.findMethod(ArgumentMatcherStorage.class,
"reportMatcher", Matcher.class);
Assert.state(method != null, "Unable to find reportMatcher method");
return method;
}
private Constructor<MockAwareVerificationMode> findMockAwareVerificationModeConstructor() {
Constructor<MockAwareVerificationMode> constructor = ClassUtils
.getConstructorIfAvailable(MockAwareVerificationMode.class,
Object.class, VerificationMode.class);
Assert.state(constructor != null,
"Unable to find MockAwareVerificationMode constructor");
return constructor;
}
@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();
}
}
}

@ -1,229 +0,0 @@
/*
* 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 java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Set;
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;
/**
* A facade for Mockito's {@link MockUtil} that hides API differences between Mockito 1
* and 2.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
final class SpringBootMockUtil {
private static final MockUtilAdapter adapter;
static {
if (ClassUtils.isPresent("org.mockito.ReturnValues",
SpringBootMockUtil.class.getClassLoader())) {
adapter = new Mockito1MockUtilAdapter();
}
else {
adapter = new Mockito2MockUtilAdapter();
}
}
private SpringBootMockUtil() {
}
static MockCreationSettings<?> getMockSettings(Object mock) {
return adapter.getMockSettings(mock);
}
static MockingProgress mockingProgress() {
return adapter.mockingProgress();
}
static void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers) {
adapter.reportMatchers(storage, matchers);
}
static MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode) {
return adapter.createMockAwareVerificationMode(mock, mode);
}
private interface MockUtilAdapter {
MockCreationSettings<?> getMockSettings(Object mock);
MockingProgress mockingProgress();
void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers);
MockAwareVerificationMode createMockAwareVerificationMode(Object mock,
VerificationMode mode);
}
private static class Mockito1MockUtilAdapter implements MockUtilAdapter {
private final MockUtil mockUtil = BeanUtils.instantiateClass(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 (MockCreationSettings<?>) ReflectionUtils
.invokeMethod(this.getMockSettingsMethod, this.mockUtil, mock);
}
@Override
public MockingProgress mockingProgress() {
return 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(mockAwareVerificationModeConstructor, mock,
mode);
}
}
private static class Mockito2MockUtilAdapter implements MockUtilAdapter {
private static final Constructor<MockAwareVerificationMode> mockAwareVerificationModeConstructor;
private static final boolean mockAwareVerificationModeLegacy;
static {
Constructor<MockAwareVerificationMode> c = getMockAwareVerificationModeConstructor();
if (c != null) {
mockAwareVerificationModeConstructor = c;
mockAwareVerificationModeLegacy = false;
}
else {
mockAwareVerificationModeConstructor = getMockAwareVerificationModeLegacyConstructor();
mockAwareVerificationModeLegacy = true;
}
}
@Override
public MockCreationSettings<?> getMockSettings(Object mock) {
return MockUtil.getMockSettings(mock);
}
@Override
public MockingProgress mockingProgress() {
return ThreadSafeMockingProgress.mockingProgress();
}
@Override
public void reportMatchers(ArgumentMatcherStorage storage,
List<LocalizedMatcher> matchers) {
for (LocalizedMatcher matcher : matchers) {
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;
}
}
}
}

@ -85,12 +85,11 @@ public class MockDefinitionTests {
new Class<?>[] { ExampleExtraInterface.class },
Answers.RETURNS_SMART_NULLS, true, MockReset.BEFORE, null);
ExampleService mock = definition.createMock();
MockCreationSettings<?> settings = SpringBootMockUtil.getMockSettings(mock);
MockCreationSettings<?> settings = MockitoApi.get().getMockSettings(mock);
assertThat(mock).isInstanceOf(ExampleService.class);
assertThat(mock).isInstanceOf(ExampleExtraInterface.class);
assertThat(settings.getMockName().toString()).isEqualTo("name");
assertThat(settings.getDefaultAnswer())
.isEqualTo(Answers.RETURNS_SMART_NULLS.get());
assertThat(settings.getDefaultAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS);
assertThat(settings.isSerializable()).isTrue();
assertThat(MockReset.get(mock)).isEqualTo(MockReset.BEFORE);
}

@ -78,11 +78,10 @@ public class SpyDefinitionTests {
SpyDefinition definition = new SpyDefinition("name", REAL_SERVICE_TYPE,
MockReset.BEFORE, true, null);
RealExampleService spy = definition.createSpy(new RealExampleService("hello"));
MockCreationSettings<?> settings = SpringBootMockUtil.getMockSettings(spy);
MockCreationSettings<?> settings = MockitoApi.get().getMockSettings(spy);
assertThat(spy).isInstanceOf(ExampleService.class);
assertThat(settings.getMockName().toString()).isEqualTo("name");
assertThat(settings.getDefaultAnswer())
.isEqualTo(Answers.CALLS_REAL_METHODS.get());
assertThat(settings.getDefaultAnswer()).isEqualTo(Answers.CALLS_REAL_METHODS);
assertThat(MockReset.get(spy)).isEqualTo(MockReset.BEFORE);
}

Loading…
Cancel
Save