Skip to content

Commit 1281f03

Browse files
committed
Skipping duplicate test classes during test AOT processing
Although it should not happen in theory, sometimes a test class is discovered more than once via the TestClassScanner in our integration tests. When it does happen in our tests, the two Class objects have the same fully-qualified class name but represent different classes which leads to failures due to incorrect associations between test class names and their MergedContextConfiguration. To address this, this commit modifies TestContextAotGenerator so that it skips duplicate test class names.
1 parent 28939e4 commit 1281f03

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.test.context.aot;
1818

1919
import java.util.Arrays;
20+
import java.util.HashSet;
2021
import java.util.LinkedHashSet;
2122
import java.util.List;
2223
import java.util.Map;
@@ -178,18 +179,27 @@ public void processAheadOfTime(Stream<Class<?>> testClasses) throws TestContextA
178179

179180
MultiValueMap<MergedContextConfiguration, Class<?>> mergedConfigMappings = new LinkedMultiValueMap<>();
180181
ClassLoader classLoader = getClass().getClassLoader();
182+
Set<String> visitedTestClassNames = new HashSet<>();
181183
testClasses.forEach(testClass -> {
182-
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
183-
mergedConfigMappings.add(mergedConfig, testClass);
184-
collectRuntimeHintsRegistrarClasses(testClass, coreRuntimeHintsRegistrarClasses);
185-
reflectiveRuntimeHintsRegistrar.registerRuntimeHints(this.runtimeHints, testClass);
186-
this.testRuntimeHintsRegistrars.forEach(registrar -> {
187-
if (logger.isTraceEnabled()) {
188-
logger.trace("Processing RuntimeHints contribution from class [%s]"
189-
.formatted(registrar.getClass().getCanonicalName()));
184+
String testClassName = testClass.getName();
185+
if (visitedTestClassNames.add(testClassName)) {
186+
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
187+
mergedConfigMappings.add(mergedConfig, testClass);
188+
collectRuntimeHintsRegistrarClasses(testClass, coreRuntimeHintsRegistrarClasses);
189+
reflectiveRuntimeHintsRegistrar.registerRuntimeHints(this.runtimeHints, testClass);
190+
this.testRuntimeHintsRegistrars.forEach(registrar -> {
191+
if (logger.isTraceEnabled()) {
192+
logger.trace("Processing RuntimeHints contribution from class [%s]"
193+
.formatted(registrar.getClass().getCanonicalName()));
194+
}
195+
registrar.registerHints(this.runtimeHints, testClass, classLoader);
196+
});
197+
}
198+
else {
199+
if (logger.isDebugEnabled()) {
200+
logger.debug("Skipping duplicate test class: " + testClassName);
190201
}
191-
registrar.registerHints(this.runtimeHints, testClass, classLoader);
192-
});
202+
}
193203
});
194204

195205
coreRuntimeHintsRegistrarClasses.stream()

0 commit comments

Comments
 (0)