2020import java .util .Set ;
2121
2222import org .junit .jupiter .api .Test ;
23+ import org .junit .jupiter .api .BeforeEach ;
2324
2425import org .springframework .ai .anthropic .api .AnthropicApi ;
2526import org .springframework .aot .hint .RuntimeHints ;
2627import org .springframework .aot .hint .TypeReference ;
28+ import org .springframework .aot .hint .MemberCategory ;
2729
2830import static org .assertj .core .api .AssertionsForClassTypes .assertThat ;
2931import static org .springframework .ai .aot .AiRuntimeHints .findJsonAnnotatedClassesInPackage ;
3032
3133class AnthropicRuntimeHintsTests {
3234
35+ private RuntimeHints runtimeHints ;
36+
37+ private AnthropicRuntimeHints anthropicRuntimeHints ;
38+
39+ @ BeforeEach
40+ void setUp () {
41+ runtimeHints = new RuntimeHints ();
42+ anthropicRuntimeHints = new AnthropicRuntimeHints ();
43+ }
44+
3345 @ Test
3446 void registerHints () {
35- RuntimeHints runtimeHints = new RuntimeHints ();
36- AnthropicRuntimeHints anthropicRuntimeHints = new AnthropicRuntimeHints ();
3747 anthropicRuntimeHints .registerHints (runtimeHints , null );
3848
3949 Set <TypeReference > jsonAnnotatedClasses = findJsonAnnotatedClassesInPackage ("org.springframework.ai.anthropic" );
@@ -55,4 +65,84 @@ void registerHints() {
5565 assertThat (registeredTypes .contains (TypeReference .of (AnthropicApi .AnthropicMessage .class ))).isTrue ();
5666 }
5767
68+ @ Test
69+ void registerHintsWithNullClassLoader () {
70+ // Test that registering hints with null ClassLoader works correctly
71+ anthropicRuntimeHints .registerHints (runtimeHints , null );
72+
73+ Set <TypeReference > registeredTypes = new HashSet <>();
74+ runtimeHints .reflection ().typeHints ().forEach (typeHint -> registeredTypes .add (typeHint .getType ()));
75+
76+ assertThat (registeredTypes .size ()).isGreaterThan (0 );
77+ }
78+
79+ @ Test
80+ void registerHintsWithCustomClassLoader () {
81+ // Test that registering hints with a custom ClassLoader works correctly
82+ ClassLoader customClassLoader = Thread .currentThread ().getContextClassLoader ();
83+ anthropicRuntimeHints .registerHints (runtimeHints , customClassLoader );
84+
85+ Set <TypeReference > registeredTypes = new HashSet <>();
86+ runtimeHints .reflection ().typeHints ().forEach (typeHint -> registeredTypes .add (typeHint .getType ()));
87+
88+ assertThat (registeredTypes .size ()).isGreaterThan (0 );
89+ }
90+
91+ @ Test
92+ void allMemberCategoriesAreRegistered () {
93+ anthropicRuntimeHints .registerHints (runtimeHints , null );
94+
95+ Set <TypeReference > jsonAnnotatedClasses = findJsonAnnotatedClassesInPackage ("org.springframework.ai.anthropic" );
96+
97+ // Verify that all MemberCategory values are registered for each type
98+ runtimeHints .reflection ().typeHints ().forEach (typeHint -> {
99+ if (jsonAnnotatedClasses .contains (typeHint .getType ())) {
100+ Set <MemberCategory > expectedCategories = Set .of (MemberCategory .values ());
101+ Set <MemberCategory > actualCategories = typeHint .getMemberCategories ();
102+ assertThat (actualCategories .containsAll (expectedCategories )).isTrue ();
103+ }
104+ });
105+ }
106+
107+ @ Test
108+ void emptyRuntimeHintsInitiallyContainsNoTypes () {
109+ // Verify that fresh RuntimeHints instance contains no reflection hints
110+ RuntimeHints emptyHints = new RuntimeHints ();
111+ Set <TypeReference > emptyRegisteredTypes = new HashSet <>();
112+ emptyHints .reflection ().typeHints ().forEach (typeHint -> emptyRegisteredTypes .add (typeHint .getType ()));
113+
114+ assertThat (emptyRegisteredTypes .size ()).isEqualTo (0 );
115+ }
116+
117+ @ Test
118+ void multipleRegistrationCallsAreIdempotent () {
119+ // Register hints multiple times and verify no duplicates
120+ anthropicRuntimeHints .registerHints (runtimeHints , null );
121+ int firstRegistrationCount = (int ) runtimeHints .reflection ().typeHints ().count ();
122+
123+ anthropicRuntimeHints .registerHints (runtimeHints , null );
124+ int secondRegistrationCount = (int ) runtimeHints .reflection ().typeHints ().count ();
125+
126+ assertThat (firstRegistrationCount ).isEqualTo (secondRegistrationCount );
127+ }
128+
129+ @ Test
130+ void verifyJsonAnnotatedClassesInPackageIsNotEmpty () {
131+ Set <TypeReference > jsonAnnotatedClasses = findJsonAnnotatedClassesInPackage ("org.springframework.ai.anthropic" );
132+ assertThat (jsonAnnotatedClasses .isEmpty ()).isFalse ();
133+ }
134+
135+ @ Test
136+ void verifyEnumTypesAreRegistered () {
137+ anthropicRuntimeHints .registerHints (runtimeHints , null );
138+
139+ Set <TypeReference > registeredTypes = new HashSet <>();
140+ runtimeHints .reflection ().typeHints ().forEach (typeHint -> registeredTypes .add (typeHint .getType ()));
141+
142+ // Verify enum types are properly registered
143+ assertThat (registeredTypes .contains (TypeReference .of (AnthropicApi .Role .class ))).isTrue ();
144+ assertThat (registeredTypes .contains (TypeReference .of (AnthropicApi .ThinkingType .class ))).isTrue ();
145+ assertThat (registeredTypes .contains (TypeReference .of (AnthropicApi .EventType .class ))).isTrue ();
146+ }
147+
58148}
0 commit comments