diff --git a/spring-boot-test/pom.xml b/spring-boot-test/pom.xml
index ed3c3f10482..89ca82682a4 100644
--- a/spring-boot-test/pom.xml
+++ b/spring-boot-test/pom.xml
@@ -112,6 +112,12 @@
true
+
+ org.jetbrains.kotlin
+ kotlin-runtime
+ 1.0.4
+ test
+
org.apache.tomcat.embed
tomcat-embed-core
diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java
index bed86e3ebd1..5e1087ed99b 100644
--- a/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java
+++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java
@@ -207,10 +207,10 @@ class ImportsContextCustomizer implements ContextCustomizer {
/**
* The key used to ensure correct application context caching. Keys are generated
- * based on all the annotations used with the test. We must use something
- * broader than just {@link Import @Import} annotations since an {@code @Import} may
- * use an {@link ImportSelector} which could make decisions based on anything
- * available from {@link AnnotationMetadata}.
+ * based on all the annotations used with the test that aren't core Java or
+ * Kotlin annotations. We must use something broader than just {@link Import @Import}
+ * annotations since an {@code @Import} may use an {@link ImportSelector} which could
+ * make decisions based on anything available from {@link AnnotationMetadata}.
*/
static class ContextCustomizerKey {
@@ -239,7 +239,8 @@ class ImportsContextCustomizer implements ContextCustomizer {
private void collectElementAnnotations(AnnotatedElement element,
Set annotations, Set> seen) {
for (Annotation annotation : element.getDeclaredAnnotations()) {
- if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) {
+ if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)
+ && !isIgnoredKotlinAnnotation(annotation)) {
annotations.add(annotation);
collectClassAnnotations(annotation.annotationType(), annotations,
seen);
@@ -247,6 +248,15 @@ class ImportsContextCustomizer implements ContextCustomizer {
}
}
+ private boolean isIgnoredKotlinAnnotation(Annotation annotation) {
+ return "kotlin.Metadata".equals(annotation.annotationType().getName())
+ || isInKotlinAnnotationPackage(annotation);
+ }
+
+ private boolean isInKotlinAnnotationPackage(Annotation annotation) {
+ return annotation.annotationType().getName().startsWith("kotlin.annotation.");
+ }
+
@Override
public int hashCode() {
return this.annotations.hashCode();
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.java
new file mode 100644
index 00000000000..dea8eaef1a6
--- /dev/null
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.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.test.context;
+
+import kotlin.Metadata;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ImportsContextCustomizer}.
+ *
+ * @author Andy Wilkinson
+ */
+public class ImportsContextCustomizerTests {
+
+ @Test
+ public void customizersForTestClassesWithDifferentKotlinMetadataAreEqual() {
+ assertThat(new ImportsContextCustomizer(FirstKotlinAnnotatedTestClass.class))
+ .isEqualTo(new ImportsContextCustomizer(
+ SecondKotlinAnnotatedTestClass.class));
+ }
+
+ @Metadata(d2 = "foo")
+ static class FirstKotlinAnnotatedTestClass {
+
+ }
+
+ @Metadata(d2 = "bar")
+ static class SecondKotlinAnnotatedTestClass {
+
+ }
+
+}