From 6e2dfc75f394f75d57b501cbdaf39245b6089d7b Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 20 Sep 2017 08:48:02 +0100 Subject: [PATCH] Drop support for Mockito 1.x Closes gh-10247 --- .../test/mock/mockito/MockDefinition.java | 2 +- .../boot/test/mock/mockito/MockReset.java | 18 +- .../MockitoAopProxyTargetInterceptor.java | 19 +- .../boot/test/mock/mockito/MockitoApi.java | 227 ------------------ .../mock/mockito/MockDefinitionTests.java | 4 +- .../test/mock/mockito/SpyDefinitionTests.java | 4 +- 6 files changed, 24 insertions(+), 250 deletions(-) delete mode 100644 spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoApi.java diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockDefinition.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockDefinition.java index 8dc93aa7ae0..36fadf227fb 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockDefinition.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockDefinition.java @@ -149,7 +149,7 @@ class MockDefinition extends Definition { if (!this.extraInterfaces.isEmpty()) { settings.extraInterfaces(this.extraInterfaces.toArray(new Class[] {})); } - settings.defaultAnswer(MockitoApi.get().getAnswer(this.answer)); + settings.defaultAnswer(this.answer); if (this.serializable) { settings.serializable(); } diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockReset.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockReset.java index 1fad5ede47f..0b02e4112b1 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockReset.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockReset.java @@ -19,13 +19,13 @@ package org.springframework.boot.test.mock.mockito; import java.util.List; import org.mockito.MockSettings; +import org.mockito.MockingDetails; import org.mockito.Mockito; import org.mockito.listeners.InvocationListener; import org.mockito.listeners.MethodInvocationReport; import org.mockito.mock.MockCreationSettings; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; /** * Reset strategy used on a mock bean. Usually applied to a mock via the @@ -100,17 +100,15 @@ public enum MockReset { * @param mock the source mock * @return the reset type (never {@code null}) */ - @SuppressWarnings("rawtypes") static MockReset get(Object mock) { MockReset reset = MockReset.NONE; - if (ClassUtils.isPresent("org.mockito.internal.util.MockUtil", null)) { - if (Mockito.mockingDetails(mock).isMock()) { - MockCreationSettings settings = MockitoApi.get().getMockSettings(mock); - List listeners = settings.getInvocationListeners(); - for (Object listener : listeners) { - if (listener instanceof ResetInvocationListener) { - reset = ((ResetInvocationListener) listener).getReset(); - } + MockingDetails mockingDetails = Mockito.mockingDetails(mock); + if (mockingDetails.isMock()) { + MockCreationSettings settings = mockingDetails.getMockCreationSettings(); + List listeners = settings.getInvocationListeners(); + for (Object listener : listeners) { + if (listener instanceof ResetInvocationListener) { + reset = ((ResetInvocationListener) listener).getReset(); } } } diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoAopProxyTargetInterceptor.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoAopProxyTargetInterceptor.java index 905c58afb8d..f33161ba08b 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoAopProxyTargetInterceptor.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoAopProxyTargetInterceptor.java @@ -16,6 +16,7 @@ package org.springframework.boot.test.mock.mockito; +import java.util.Collections; import java.util.List; import org.aopalliance.aop.Advice; @@ -25,6 +26,7 @@ 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.progress.ThreadSafeMockingProgress; import org.mockito.internal.verification.MockAwareVerificationMode; import org.mockito.verification.VerificationMode; @@ -48,12 +50,11 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { private final Object target; - private final Verification verification; + private final Verification verification = new Verification(); MockitoAopProxyTargetInterceptor(Object source, Object target) throws Exception { this.source = source; this.target = target; - this.verification = new Verification(target); } @Override @@ -89,11 +90,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { private final Object monitor = new Object(); - private final MockingProgress progress; - - Verification(Object target) { - this.progress = MockitoApi.get().mockingProgress(target); - } + private final MockingProgress progress = ThreadSafeMockingProgress + .mockingProgress(); public boolean isVerifying() { synchronized (this.monitor) { @@ -113,8 +111,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { if (mode instanceof MockAwareVerificationMode) { MockAwareVerificationMode mockAwareMode = (MockAwareVerificationMode) mode; if (mockAwareMode.getMock() == source) { - mode = MockitoApi.get().createMockAwareVerificationMode( - target, mockAwareMode); + mode = new MockAwareVerificationMode(target, mode, + Collections.emptySet()); } } resetVerificationStarted(mode); @@ -126,7 +124,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { ArgumentMatcherStorage storage = this.progress.getArgumentMatcherStorage(); List matchers = storage.pullLocalizedMatchers(); this.progress.verificationStarted(mode); - MockitoApi.get().reportMatchers(storage, matchers); + matchers.stream().map(LocalizedMatcher::getMatcher) + .forEach(storage::reportMatcher); } } diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoApi.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoApi.java deleted file mode 100644 index f33df4754b6..00000000000 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoApi.java +++ /dev/null @@ -1,227 +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.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; -import org.mockito.stubbing.Answer; -import org.mockito.verification.VerificationMode; - -import org.springframework.beans.BeanUtils; -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. - * @param mock the mock object - * @return the current mocking progress - */ - public abstract MockingProgress mockingProgress(Object mock); - - /** - * 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 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 getAnswer(Answers answer); - - /** - * Factory to create the appropriate API version. - * @return the API version - */ - private static MockitoApi createApi() { - if (ClassUtils.isPresent("org.mockito.ReturnValues", null)) { - return new Mockito1Api(); - } - return new Mockito2Api(); - } - - /** - * Get the API for the running mockito version. - * @return the API - */ - public static MockitoApi get() { - 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 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 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 getAnswer(Answers answer) { - return answer.get(); - } - - } - - /** - * {@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(Object mock) { - return ThreadSafeMockingProgress.mockingProgress(); - } - - @Override - public void reportMatchers(ArgumentMatcherStorage storage, - List 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 constructor = ClassUtils - .getConstructorIfAvailable(MockAwareVerificationMode.class, - Object.class, VerificationMode.class); - if (constructor == null) { - throw ex; - } - return BeanUtils.instantiateClass(constructor, mock, mode); - } - } - - @Override - public Answer getAnswer(Answers answer) { - return answer; - } - - } - -} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockDefinitionTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockDefinitionTests.java index 2d6bbe1f4a4..e78f231f83d 100644 --- a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockDefinitionTests.java +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockDefinitionTests.java @@ -20,6 +20,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Answers; +import org.mockito.Mockito; import org.mockito.mock.MockCreationSettings; import org.springframework.boot.test.mock.mockito.example.ExampleExtraInterface; @@ -85,7 +86,8 @@ public class MockDefinitionTests { new Class[] { ExampleExtraInterface.class }, Answers.RETURNS_SMART_NULLS, true, MockReset.BEFORE, null); ExampleService mock = definition.createMock(); - MockCreationSettings settings = MockitoApi.get().getMockSettings(mock); + MockCreationSettings settings = Mockito.mockingDetails(mock) + .getMockCreationSettings(); assertThat(mock).isInstanceOf(ExampleService.class); assertThat(mock).isInstanceOf(ExampleExtraInterface.class); assertThat(settings.getMockName().toString()).isEqualTo("name"); diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyDefinitionTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyDefinitionTests.java index 407df2d4739..673ccb3eeee 100644 --- a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyDefinitionTests.java +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyDefinitionTests.java @@ -20,6 +20,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Answers; +import org.mockito.Mockito; import org.mockito.mock.MockCreationSettings; import org.springframework.boot.test.mock.mockito.example.ExampleService; @@ -78,7 +79,8 @@ public class SpyDefinitionTests { SpyDefinition definition = new SpyDefinition("name", REAL_SERVICE_TYPE, MockReset.BEFORE, true, null); RealExampleService spy = definition.createSpy(new RealExampleService("hello")); - MockCreationSettings settings = MockitoApi.get().getMockSettings(spy); + MockCreationSettings settings = Mockito.mockingDetails(spy) + .getMockCreationSettings(); assertThat(spy).isInstanceOf(ExampleService.class); assertThat(settings.getMockName().toString()).isEqualTo("name"); assertThat(settings.getDefaultAnswer()).isEqualTo(Answers.CALLS_REAL_METHODS);