From 246833329fd4a3b1f218265fc2b62f7e907b3639 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 27 Nov 2023 15:42:20 +0100 Subject: [PATCH] Register runtime hints for skipped exceptions in the TestContext framework Closes gh-31479 --- .../test/context/aot/TestContextAotGenerator.java | 15 +++++++++++++++ .../context/aot/TestContextAotGeneratorTests.java | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java index 25e27f7b2f41..dd52fe402536 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java @@ -205,6 +205,7 @@ public void processAheadOfTime(Stream> testClasses) throws TestContextA MultiValueMap> initializerClassMappings = processAheadOfTime(mergedConfigMappings); generateAotTestContextInitializerMappings(initializerClassMappings); generateAotTestAttributeMappings(); + registerSkippedExceptionTypes(); } finally { resetAotFactories(); @@ -422,6 +423,20 @@ private void registerDeclaredConstructors(Class type) { this.runtimeHints.reflection().registerType(type, INVOKE_DECLARED_CONSTRUCTORS); } + /** + * Register hints for skipped exception types loaded via reflection in + * {@link org.springframework.test.context.TestContextManager}. + * @since 6.1.2 + */ + private void registerSkippedExceptionTypes() { + Stream.of( + "org.opentest4j.TestAbortedException", + "org.junit.AssumptionViolatedException", + "org.testng.SkipException") + .map(TypeReference::of) + .forEach(this.runtimeHints.reflection()::registerType); + } + private static boolean getFailOnErrorFlag() { String failOnError = SpringProperties.getProperty(FAIL_ON_ERROR_PROPERTY_NAME); if (StringUtils.hasText(failOnError)) { diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorTests.java index ecdc96d7297b..26e9651f725c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorTests.java @@ -158,6 +158,12 @@ private static void assertRuntimeHints(RuntimeHints runtimeHints) { assertReflectionRegistered(runtimeHints, AotTestContextInitializersCodeGenerator.GENERATED_MAPPINGS_CLASS_NAME, INVOKE_PUBLIC_METHODS); assertReflectionRegistered(runtimeHints, AotTestAttributesCodeGenerator.GENERATED_ATTRIBUTES_CLASS_NAME, INVOKE_PUBLIC_METHODS); + Stream.of( + "org.opentest4j.TestAbortedException", + "org.junit.AssumptionViolatedException", + "org.testng.SkipException" + ).forEach(type -> assertReflectionRegistered(runtimeHints, type)); + Stream.of( org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.class, org.springframework.test.context.support.DefaultBootstrapContext.class @@ -239,6 +245,12 @@ private static void assertRuntimeHints(RuntimeHints runtimeHints) { .accepts(runtimeHints); } + private static void assertReflectionRegistered(RuntimeHints runtimeHints, String type) { + assertThat(reflection().onType(TypeReference.of(type))) + .as("Reflection hint for %s", type) + .accepts(runtimeHints); + } + private static void assertReflectionRegistered(RuntimeHints runtimeHints, String type, MemberCategory memberCategory) { assertThat(reflection().onType(TypeReference.of(type)).withMemberCategory(memberCategory)) .as("Reflection hint for %s with category %s", type, memberCategory)