diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementServerPropertiesAutoConfigurationNoSecurityTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementServerPropertiesAutoConfigurationNoSecurityTests.java
index af7700e92f..1060636db4 100644
--- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementServerPropertiesAutoConfigurationNoSecurityTests.java
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementServerPropertiesAutoConfigurationNoSecurityTests.java
@@ -22,7 +22,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,7 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Stephane Nicoll
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("spring-security-*.jar")
public class ManagementServerPropertiesAutoConfigurationNoSecurityTests {
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java
index 2ddb91701e..0feaf7f230 100644
--- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java
@@ -31,7 +31,7 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mock.web.MockServletContext;
@@ -49,7 +49,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("spring-security-*.jar")
public class NoSpringSecurityHealthMvcEndpointIntegrationTests {
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/OnBeanConditionTypeDeductionFailureTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/OnBeanConditionTypeDeductionFailureTests.java
index 272834d4a5..0236b94ddf 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/OnBeanConditionTypeDeductionFailureTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/OnBeanConditionTypeDeductionFailureTests.java
@@ -22,7 +22,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.condition.OnBeanCondition.BeanTypeDeductionException;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -38,7 +38,7 @@ import static org.junit.Assert.fail;
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("jackson-core-*.jar")
public class OnBeanConditionTypeDeductionFailureTests {
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBeanCreationFailureAnalyzerTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBeanCreationFailureAnalyzerTests.java
index dbaeb9a112..5a044d4143 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBeanCreationFailureAnalyzerTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBeanCreationFailureAnalyzerTests.java
@@ -23,7 +23,7 @@ import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
@@ -34,7 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions({ "h2-*.jar", "hsqldb-*.jar" })
public class DataSourceBeanCreationFailureAnalyzerTests {
diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsEmbeddedDataSourceAutoConfigurationTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsEmbeddedDataSourceAutoConfigurationTests.java
index 4442faa9ff..9fc1a9eddf 100644
--- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsEmbeddedDataSourceAutoConfigurationTests.java
+++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/DevToolsEmbeddedDataSourceAutoConfigurationTests.java
@@ -26,7 +26,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import org.springframework.context.ConfigurableApplicationContext;
import static org.mockito.Mockito.times;
@@ -37,7 +37,7 @@ import static org.mockito.Mockito.verify;
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("tomcat-jdbc-*.jar")
public class DevToolsEmbeddedDataSourceAutoConfigurationTests
extends AbstractDevToolsDataSourceAutoConfigurationTests {
diff --git a/spring-boot-docs/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderExampleTests.java b/spring-boot-docs/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderExampleTests.java
index 0287b21da8..9927cf0912 100644
--- a/spring-boot-docs/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderExampleTests.java
+++ b/spring-boot-docs/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderExampleTests.java
@@ -22,7 +22,7 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("spring-web-*.jar")
public class SpringApplicationBuilderExampleTests {
diff --git a/spring-boot-test/pom.xml b/spring-boot-test/pom.xml
index a0afed221a..d9f03e8234 100644
--- a/spring-boot-test/pom.xml
+++ b/spring-boot-test/pom.xml
@@ -112,6 +112,12 @@
true
+
+ org.springframework.boot
+ spring-boot
+ test-jar
+ test
+
org.jetbrains.kotlin
kotlin-runtime
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 5cef1c2cc5..63eab8bce5 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
@@ -20,7 +20,6 @@ import java.util.List;
import org.mockito.MockSettings;
import org.mockito.Mockito;
-import org.mockito.internal.util.MockUtil;
import org.mockito.listeners.InvocationListener;
import org.mockito.listeners.MethodInvocationReport;
import org.mockito.mock.MockCreationSettings;
@@ -105,9 +104,8 @@ public enum MockReset {
static MockReset get(Object mock) {
MockReset reset = MockReset.NONE;
if (ClassUtils.isPresent("org.mockito.internal.util.MockUtil", null)) {
- MockUtil mockUtil = new MockUtil();
- if (mockUtil.isMock(mock)) {
- MockCreationSettings settings = mockUtil.getMockSettings(mock);
+ if (Mockito.mockingDetails(mock).isMock()) {
+ MockCreationSettings settings = SpringBootMockUtil.getMockSettings(mock);
List listeners = settings.getInvocationListeners();
for (Object listener : listeners) {
if (listener instanceof ResetInvocationListener) {
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 19507b27b8..1824c648a4 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,19 +16,14 @@
package org.springframework.boot.test.mock.mockito;
-import java.lang.reflect.Field;
import java.util.List;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.Interceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
-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.stubbing.InvocationContainer;
-import org.mockito.internal.util.MockUtil;
import org.mockito.internal.verification.MockAwareVerificationMode;
import org.mockito.verification.VerificationMode;
@@ -38,7 +33,6 @@ import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.util.AopTestUtils;
import org.springframework.util.Assert;
-import org.springframework.util.ReflectionUtils;
/**
* AOP {@link Interceptor} that attempts to make AOP proxy beans work with Mockito. Works
@@ -58,7 +52,7 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
MockitoAopProxyTargetInterceptor(Object source, Object target) throws Exception {
this.source = source;
this.target = target;
- this.verification = new Verification(target);
+ this.verification = new Verification();
}
@Override
@@ -94,21 +88,10 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
private final Object monitor = new Object();
- private final MockingProgress progress;
-
- Verification(Object target) {
- MockUtil mockUtil = new MockUtil();
- InternalMockHandler> handler = mockUtil.getMockHandler(target);
- InvocationContainer container = handler.getInvocationContainer();
- Field field = ReflectionUtils.findField(container.getClass(),
- "mockingProgress");
- ReflectionUtils.makeAccessible(field);
- this.progress = (MockingProgress) ReflectionUtils.getField(field, container);
- }
-
public boolean isVerifying() {
synchronized (this.monitor) {
- VerificationMode mode = this.progress.pullVerificationMode();
+ VerificationMode mode = SpringBootMockUtil.mockingProgress()
+ .pullVerificationMode();
if (mode != null) {
resetVerificationStarted(mode);
return true;
@@ -119,7 +102,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
public void replaceVerifyMock(Object source, Object target) {
synchronized (this.monitor) {
- VerificationMode mode = this.progress.pullVerificationMode();
+ VerificationMode mode = SpringBootMockUtil.mockingProgress()
+ .pullVerificationMode();
if (mode != null) {
if (mode instanceof MockAwareVerificationMode) {
MockAwareVerificationMode mockAwareMode = (MockAwareVerificationMode) mode;
@@ -133,12 +117,11 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
}
private void resetVerificationStarted(VerificationMode mode) {
- ArgumentMatcherStorage storage = this.progress.getArgumentMatcherStorage();
+ ArgumentMatcherStorage storage = SpringBootMockUtil.mockingProgress()
+ .getArgumentMatcherStorage();
List matchers = storage.pullLocalizedMatchers();
- this.progress.verificationStarted(mode);
- for (LocalizedMatcher matcher : matchers) {
- storage.reportMatcher(matcher);
- }
+ SpringBootMockUtil.mockingProgress().verificationStarted(mode);
+ SpringBootMockUtil.reportMatchers(storage, matchers);
}
}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpringBootMockUtil.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpringBootMockUtil.java
new file mode 100644
index 0000000000..f47dc11dec
--- /dev/null
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpringBootMockUtil.java
@@ -0,0 +1,138 @@
+/*
+ * 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.Method;
+import java.util.List;
+
+import org.mockito.ArgumentMatcher;
+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.mock.MockCreationSettings;
+
+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
+ */
+class SpringBootMockUtil {
+
+ private static final MockUtilAdapter adapter;
+
+ static {
+ if (ClassUtils.isPresent("org.mockito.quality.MockitoHint",
+ SpringBootMockUtil.class.getClassLoader())) {
+ adapter = new Mockito2MockUtilAdapter();
+ }
+ else {
+ adapter = new Mockito1MockUtilAdapter();
+ }
+ }
+
+ static MockCreationSettings> getMockSettings(Object mock) {
+ return adapter.getMockSettings(mock);
+ }
+
+ static MockingProgress mockingProgress() {
+ return adapter.mockingProgress();
+ }
+
+ static void reportMatchers(ArgumentMatcherStorage storage,
+ List matchers) {
+ adapter.reportMatchers(storage, matchers);
+ }
+
+ private interface MockUtilAdapter {
+
+ MockCreationSettings> getMockSettings(Object mock);
+
+ MockingProgress mockingProgress();
+
+ void reportMatchers(ArgumentMatcherStorage storage,
+ List matchers);
+
+ }
+
+ private static class Mockito1MockUtilAdapter implements MockUtilAdapter {
+
+ private static final MockingProgress mockingProgress = new ThreadSafeMockingProgress();
+
+ @Override
+ public MockCreationSettings> getMockSettings(Object mock) {
+ return new MockUtil().getMockSettings(mock);
+ }
+
+ @Override
+ public MockingProgress mockingProgress() {
+ return mockingProgress;
+ }
+
+ @Override
+ public void reportMatchers(ArgumentMatcherStorage storage,
+ List matchers) {
+ for (LocalizedMatcher matcher : matchers) {
+ storage.reportMatcher(matcher);
+ }
+ }
+
+ }
+
+ private static class Mockito2MockUtilAdapter implements MockUtilAdapter {
+
+ private final Method getMockSettingsMethod = ReflectionUtils
+ .findMethod(MockUtil.class, "getMockSettings", Object.class);
+
+ 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");
+
+ @Override
+ public MockCreationSettings> getMockSettings(Object mock) {
+ return (MockCreationSettings>) ReflectionUtils
+ .invokeMethod(this.getMockSettingsMethod, null, mock);
+ }
+
+ @Override
+ public MockingProgress mockingProgress() {
+ return (MockingProgress) ReflectionUtils
+ .invokeMethod(this.mockingProgressMethod, null);
+ }
+
+ @Override
+ public void reportMatchers(ArgumentMatcherStorage storage,
+ List matchers) {
+ for (LocalizedMatcher matcher : matchers) {
+ ReflectionUtils.invokeMethod(this.reportMatcherMethod, storage,
+ ReflectionUtils.invokeMethod(this.getMatcherMethod, matcher));
+ }
+ }
+
+ }
+
+}
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpyDefinition.java b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpyDefinition.java
index 252dd8ce6b..172b05aed2 100644
--- a/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpyDefinition.java
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/SpyDefinition.java
@@ -18,7 +18,6 @@ package org.springframework.boot.test.mock.mockito;
import org.mockito.MockSettings;
import org.mockito.Mockito;
-import org.mockito.internal.util.MockUtil;
import org.springframework.core.ResolvableType;
import org.springframework.core.style.ToStringCreator;
@@ -33,8 +32,6 @@ import org.springframework.util.StringUtils;
*/
class SpyDefinition extends Definition {
- private MockUtil mockUtil = new MockUtil();
-
private static final int MULTIPLIER = 31;
private final ResolvableType typeToSpy;
@@ -87,7 +84,7 @@ class SpyDefinition extends Definition {
public T createSpy(String name, Object instance) {
Assert.notNull(instance, "Instance must not be null");
Assert.isInstanceOf(this.typeToSpy.resolve(), instance);
- if (this.mockUtil.isSpy(instance)) {
+ if (Mockito.mockingDetails(instance).isSpy()) {
return (T) instance;
}
MockSettings settings = MockReset.withSettings(getReset());
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 4f4dcbda24..cb8eaa8fea 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,7 +20,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
-import org.mockito.internal.util.MockUtil;
import org.mockito.mock.MockCreationSettings;
import org.springframework.boot.test.mock.mockito.example.ExampleExtraInterface;
@@ -86,7 +85,7 @@ public class MockDefinitionTests {
new Class>[] { ExampleExtraInterface.class },
Answers.RETURNS_SMART_NULLS, true, MockReset.BEFORE, null);
ExampleService mock = definition.createMock();
- MockCreationSettings> settings = new MockUtil().getMockSettings(mock);
+ MockCreationSettings> settings = SpringBootMockUtil.getMockSettings(mock);
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/Mockito21Tests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/Mockito21Tests.java
new file mode 100644
index 0000000000..495a772080
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/Mockito21Tests.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+
+import org.springframework.boot.testutil.ClassPathOverrides;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for compatibility with Mockito 2.1
+ *
+ * @author Andy Wilkinson
+ */
+@RunWith(ModifiedClassPathRunner.class)
+@ClassPathOverrides("org.mockito:mockito-core:2.1.0")
+public class Mockito21Tests {
+
+ @Test
+ public void resetMocksTestExecutionListenerTestsWithMockito2() {
+ runTests(ResetMocksTestExecutionListenerTests.class);
+ }
+
+ @Test
+ public void spyBeanWithAopProxyTestsWithMockito2() {
+ runTests(SpyBeanWithAopProxyTests.class);
+ }
+
+ private void runTests(Class> testClass) {
+ Result result = new JUnitCore().run(testClass);
+ assertThat(result.getFailureCount()).isEqualTo(0);
+ assertThat(result.getRunCount()).isGreaterThan(0);
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/Mockito22Tests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/Mockito22Tests.java
new file mode 100644
index 0000000000..57df08053a
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/Mockito22Tests.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+
+import org.springframework.boot.testutil.ClassPathOverrides;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for compatibility with Mockito 2.2
+ *
+ * @author Andy Wilkinson
+ */
+@RunWith(ModifiedClassPathRunner.class)
+@ClassPathOverrides("org.mockito:mockito-core:2.2.0")
+public class Mockito22Tests {
+
+ @Test
+ public void resetMocksTestExecutionListenerTestsWithMockito2() {
+ runTests(ResetMocksTestExecutionListenerTests.class);
+ }
+
+ @Test
+ public void spyBeanWithAopProxyTestsWithMockito2() {
+ runTests(SpyBeanWithAopProxyTests.class);
+ }
+
+ private void runTests(Class> testClass) {
+ Result result = new JUnitCore().run(testClass);
+ assertThat(result.getFailureCount()).isEqualTo(0);
+ assertThat(result.getRunCount()).isGreaterThan(0);
+ }
+
+}
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java
index 8bfc6d9b1f..c9a1a55ae3 100644
--- a/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java
@@ -19,7 +19,7 @@ package org.springframework.boot.test.mock.mockito;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.mockito.internal.util.MockUtil;
+import org.mockito.Mockito;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -80,7 +80,8 @@ public class MockitoPostProcessorTests {
context.registerBeanDefinition("beanToBeMocked", factoryBeanDefinition);
context.register(MockedFactoryBean.class);
context.refresh();
- assertThat(new MockUtil().isMock(context.getBean("beanToBeMocked"))).isTrue();
+ assertThat(Mockito.mockingDetails(context.getBean("beanToBeMocked")).isMock())
+ .isTrue();
}
@Configuration
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 b92af3d2b5..47b800bbd2 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,7 +20,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
-import org.mockito.internal.util.MockUtil;
import org.mockito.mock.MockCreationSettings;
import org.springframework.boot.test.mock.mockito.example.ExampleService;
@@ -79,7 +78,7 @@ public class SpyDefinitionTests {
SpyDefinition definition = new SpyDefinition("name", REAL_SERVICE_TYPE,
MockReset.BEFORE, true, null);
RealExampleService spy = definition.createSpy(new RealExampleService("hello"));
- MockCreationSettings> settings = new MockUtil().getMockSettings(spy);
+ MockCreationSettings> settings = SpringBootMockUtil.getMockSettings(spy);
assertThat(spy).isInstanceOf(ExampleService.class);
assertThat(settings.getMockName().toString()).isEqualTo("name");
assertThat(settings.getDefaultAnswer())
diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml
index 5eb19b4b47..16b412cab1 100644
--- a/spring-boot/pom.xml
+++ b/spring-boot/pom.xml
@@ -290,6 +290,64 @@
org.apache.httpcomponents
httpasyncclient
test
+
+
+ org.apache.maven
+ maven-aether-provider
+
+
+ org.eclipse.sisu.plexus
+ org.eclipse.sisu
+
+
+
+
+ org.apache.maven
+ maven-settings-builder
+
+
+ org.codehaus.plexus
+ plexus-component-api
+
+
+ *
+ *
+
+
+
+
+ org.eclipse.aether
+ aether-api
+
+
+ org.eclipse.aether
+ aether-connector-basic
+
+
+ org.eclipse.aether
+ aether-impl
+
+
+ org.eclipse.aether
+ aether-spi
+
+
+ org.eclipse.aether
+ aether-transport-file
+
+
+ org.eclipse.aether
+ aether-transport-http
+
+
+ jcl-over-slf4j
+ org.slf4j
+
+
+
+
+ org.eclipse.aether
+ aether-util
org.firebirdsql.jdbc
diff --git a/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java b/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java
index 14ebd3061f..e70e949f96 100644
--- a/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java
@@ -23,7 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.testutil.ClassPathExclusions;
-import org.springframework.boot.testutil.FilteredClassPathRunner;
+import org.springframework.boot.testutil.ModifiedClassPathRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@@ -34,7 +34,7 @@ import static org.junit.Assert.fail;
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("hibernate-validator-*.jar")
public class ValidationExceptionFailureAnalyzerTests {
diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathExclusions.java b/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathExclusions.java
index 3781a38ec7..b42c053a64 100644
--- a/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathExclusions.java
+++ b/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathExclusions.java
@@ -23,7 +23,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Annotation used in combination with {@link FilteredClassPathRunner} to exclude entries
+ * Annotation used in combination with {@link ModifiedClassPathRunner} to exclude entries
* from the classpath.
*
* @author Andy Wilkinson
diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathOverrides.java b/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathOverrides.java
new file mode 100644
index 0000000000..93af3c074e
--- /dev/null
+++ b/spring-boot/src/test/java/org/springframework/boot/testutil/ClassPathOverrides.java
@@ -0,0 +1,42 @@
+/*
+ * 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.testutil;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used in combination with {@link ModifiedClassPathRunner} to override entries
+ * on the classpath.
+ *
+ * @author Andy Wilkinson
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ClassPathOverrides {
+
+ /**
+ * One or more sets of Maven coordinates ({@code groupId:artifactId:version}) to be
+ * added to the classpath. The additions will take precedence over any existing
+ * classes on the classpath.
+ * @return the coordinates
+ */
+ String[] value();
+
+}
diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java b/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunner.java
similarity index 64%
rename from spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java
rename to spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunner.java
index c89aa161e7..c7f05b4866 100644
--- a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunner.java
+++ b/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunner.java
@@ -28,6 +28,22 @@ import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
+import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.impl.DefaultServiceLocator;
+import org.eclipse.aether.repository.LocalRepository;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.resolution.DependencyRequest;
+import org.eclipse.aether.resolution.DependencyResult;
+import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
+import org.eclipse.aether.spi.connector.transport.TransporterFactory;
+import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
@@ -38,16 +54,17 @@ import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
/**
- * A custom {@link BlockJUnit4ClassRunner} that runs tests using a filtered class path.
- * Entries are excluded from the class path using {@link ClassPathExclusions} on the test
- * class. A class loader is created with the customized class path and is used both to
- * load the test class and as the thread context class loader while the test is being run.
+ * A custom {@link BlockJUnit4ClassRunner} that runs tests using a modified class path.
+ * Entries are excluded from the class path using {@link ClassPathExclusions} and
+ * overridden using {@link ClassPathOverrides} on the test class. A class loader is
+ * created with the customized class path and is used both to load the test class and as
+ * the thread context class loader while the test is being run.
*
* @author Andy Wilkinson
*/
-public class FilteredClassPathRunner extends BlockJUnit4ClassRunner {
+public class ModifiedClassPathRunner extends BlockJUnit4ClassRunner {
- public FilteredClassPathRunner(Class> testClass) throws InitializationError {
+ public ModifiedClassPathRunner(Class> testClass) throws InitializationError {
super(testClass);
}
@@ -64,7 +81,7 @@ public class FilteredClassPathRunner extends BlockJUnit4ClassRunner {
private URLClassLoader createTestClassLoader(Class> testClass) throws Exception {
URLClassLoader classLoader = (URLClassLoader) this.getClass().getClassLoader();
- return new FilteredClassLoader(filterUrls(extractUrls(classLoader), testClass),
+ return new FilteredClassLoader(processUrls(extractUrls(classLoader), testClass),
classLoader.getParent(), classLoader);
}
@@ -104,15 +121,61 @@ public class FilteredClassPathRunner extends BlockJUnit4ClassRunner {
}
}
- private URL[] filterUrls(URL[] urls, Class> testClass) throws Exception {
+ private URL[] processUrls(URL[] urls, Class> testClass) throws Exception {
ClassPathEntryFilter filter = new ClassPathEntryFilter(testClass);
- List filteredUrls = new ArrayList();
+ List processedUrls = new ArrayList();
+ processedUrls.addAll(getAdditionalUrls(testClass));
for (URL url : urls) {
if (!filter.isExcluded(url)) {
- filteredUrls.add(url);
+ processedUrls.add(url);
}
}
- return filteredUrls.toArray(new URL[filteredUrls.size()]);
+ return processedUrls.toArray(new URL[processedUrls.size()]);
+ }
+
+ private List getAdditionalUrls(Class> testClass) throws Exception {
+ ClassPathOverrides overrides = AnnotationUtils.findAnnotation(testClass,
+ ClassPathOverrides.class);
+ if (overrides == null) {
+ return Collections.emptyList();
+ }
+ return resolveCoordinates(overrides.value());
+ }
+
+ private List resolveCoordinates(String[] coordinates) throws Exception {
+ DefaultServiceLocator serviceLocator = MavenRepositorySystemUtils
+ .newServiceLocator();
+ serviceLocator.addService(RepositoryConnectorFactory.class,
+ BasicRepositoryConnectorFactory.class);
+ serviceLocator.addService(TransporterFactory.class, HttpTransporterFactory.class);
+ RepositorySystem repositorySystem = serviceLocator
+ .getService(RepositorySystem.class);
+ DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
+ LocalRepository localRepository = new LocalRepository(
+ System.getProperty("user.home") + "/.m2/repository");
+ session.setLocalRepositoryManager(
+ repositorySystem.newLocalRepositoryManager(session, localRepository));
+ CollectRequest collectRequest = new CollectRequest(null,
+ Arrays.asList(new RemoteRepository.Builder("central", "default",
+ "http://central.maven.org/maven2").build()));
+
+ collectRequest.setDependencies(createDependencies(coordinates));
+ DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null);
+ DependencyResult result = repositorySystem.resolveDependencies(session,
+ dependencyRequest);
+ List resolvedArtifacts = new ArrayList();
+ for (ArtifactResult artifact : result.getArtifactResults()) {
+ resolvedArtifacts.add(artifact.getArtifact().getFile().toURI().toURL());
+ }
+ return resolvedArtifacts;
+ }
+
+ private List createDependencies(String[] allCoordinates) {
+ List dependencies = new ArrayList();
+ for (String coordinates : allCoordinates) {
+ dependencies.add(new Dependency(new DefaultArtifact(coordinates), null));
+ }
+ return dependencies;
}
/**
diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java b/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunnerExclusionsTests.java
similarity index 88%
rename from spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java
rename to spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunnerExclusionsTests.java
index 73ef93cb80..40803d8e4b 100644
--- a/spring-boot/src/test/java/org/springframework/boot/testutil/FilteredClassPathRunnerTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunnerExclusionsTests.java
@@ -22,13 +22,13 @@ import org.junit.runner.RunWith;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests for {@link FilteredClassPathRunner}
+ * Tests for {@link ModifiedClassPathRunner} excluding entries from the class path.
*
* @author Andy Wilkinson
*/
-@RunWith(FilteredClassPathRunner.class)
+@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("hibernate-validator-*.jar")
-public class FilteredClassPathRunnerTests {
+public class ModifiedClassPathRunnerExclusionsTests {
private static final String EXCLUDED_RESOURCE = "META-INF/services/"
+ "javax.validation.spi.ValidationProvider";
diff --git a/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunnerOverridesTests.java b/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunnerOverridesTests.java
new file mode 100644
index 0000000000..8d51b23034
--- /dev/null
+++ b/spring-boot/src/test/java/org/springframework/boot/testutil/ModifiedClassPathRunnerOverridesTests.java
@@ -0,0 +1,48 @@
+/*
+ * 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.testutil;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.util.StringUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ModifiedClassPathRunner} overriding entries on the class path.
+ *
+ * @author Andy Wilkinson
+ */
+@RunWith(ModifiedClassPathRunner.class)
+@ClassPathOverrides("org.springframework:spring-context:4.1.0.RELEASE")
+public class ModifiedClassPathRunnerOverridesTests {
+
+ @Test
+ public void classesAreLoadedFromOverride() {
+ assertThat(ApplicationContext.class.getProtectionDomain().getCodeSource()
+ .getLocation().toString()).endsWith("spring-context-4.1.0.RELEASE.jar");
+ }
+
+ @Test
+ public void classesAreLoadedFromTransitiveDependencyOfOverride() {
+ assertThat(StringUtils.class.getProtectionDomain().getCodeSource().getLocation()
+ .toString()).endsWith("spring-core-4.1.0.RELEASE.jar");
+ }
+
+}