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.
This commit is contained in:
Sam Brannen 2023-10-16 16:05:09 +02:00
parent 28939e4754
commit 1281f03b96
1 changed files with 20 additions and 10 deletions

View File

@ -17,6 +17,7 @@
package org.springframework.test.context.aot;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -178,18 +179,27 @@ public class TestContextAotGenerator {
MultiValueMap<MergedContextConfiguration, Class<?>> mergedConfigMappings = new LinkedMultiValueMap<>();
ClassLoader classLoader = getClass().getClassLoader();
Set<String> visitedTestClassNames = new HashSet<>();
testClasses.forEach(testClass -> {
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
mergedConfigMappings.add(mergedConfig, testClass);
collectRuntimeHintsRegistrarClasses(testClass, coreRuntimeHintsRegistrarClasses);
reflectiveRuntimeHintsRegistrar.registerRuntimeHints(this.runtimeHints, testClass);
this.testRuntimeHintsRegistrars.forEach(registrar -> {
if (logger.isTraceEnabled()) {
logger.trace("Processing RuntimeHints contribution from class [%s]"
.formatted(registrar.getClass().getCanonicalName()));
String testClassName = testClass.getName();
if (visitedTestClassNames.add(testClassName)) {
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
mergedConfigMappings.add(mergedConfig, testClass);
collectRuntimeHintsRegistrarClasses(testClass, coreRuntimeHintsRegistrarClasses);
reflectiveRuntimeHintsRegistrar.registerRuntimeHints(this.runtimeHints, testClass);
this.testRuntimeHintsRegistrars.forEach(registrar -> {
if (logger.isTraceEnabled()) {
logger.trace("Processing RuntimeHints contribution from class [%s]"
.formatted(registrar.getClass().getCanonicalName()));
}
registrar.registerHints(this.runtimeHints, testClass, classLoader);
});
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping duplicate test class: " + testClassName);
}
registrar.registerHints(this.runtimeHints, testClass, classLoader);
});
}
});
coreRuntimeHintsRegistrarClasses.stream()