Skip to content

Commit cc17639

Browse files
alxkmWillam2004
authored andcommitted
Enhance AnthropicChatOptions test coverage (spring-projects#3973)
Add comprehensive test coverage for AnthropicChatOptions - Add new test methods covering edge cases and object behavior - Test collection handling, copy behavior, and API completeness - Enhance validation of equals/hashCode contracts and null safety Signed-off-by: Alex Klimenko <[email protected]> Signed-off-by: 家娃 <[email protected]>
1 parent 977b0e6 commit cc17639

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed

models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatOptionsTests.java

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.ai.anthropic;
1818

19+
import java.util.Collections;
1920
import java.util.List;
2021
import java.util.Map;
2122

@@ -101,4 +102,220 @@ void testDefaultValues() {
101102
assertThat(options.getMetadata()).isNull();
102103
}
103104

105+
@Test
106+
void testBuilderWithEmptyCollections() {
107+
AnthropicChatOptions options = AnthropicChatOptions.builder()
108+
.stopSequences(Collections.emptyList())
109+
.toolContext(Collections.emptyMap())
110+
.build();
111+
112+
assertThat(options.getStopSequences()).isEmpty();
113+
assertThat(options.getToolContext()).isEmpty();
114+
}
115+
116+
@Test
117+
void testBuilderWithSingleElementCollections() {
118+
AnthropicChatOptions options = AnthropicChatOptions.builder()
119+
.stopSequences(List.of("single-stop"))
120+
.toolContext(Map.of("single-key", "single-value"))
121+
.build();
122+
123+
assertThat(options.getStopSequences()).hasSize(1).containsExactly("single-stop");
124+
assertThat(options.getToolContext()).hasSize(1).containsEntry("single-key", "single-value");
125+
}
126+
127+
@Test
128+
void testCopyWithEmptyOptions() {
129+
AnthropicChatOptions emptyOptions = new AnthropicChatOptions();
130+
AnthropicChatOptions copiedOptions = emptyOptions.copy();
131+
132+
assertThat(copiedOptions).isNotSameAs(emptyOptions).isEqualTo(emptyOptions);
133+
assertThat(copiedOptions.getModel()).isNull();
134+
assertThat(copiedOptions.getMaxTokens()).isNull();
135+
assertThat(copiedOptions.getTemperature()).isNull();
136+
}
137+
138+
@Test
139+
void testCopyMutationDoesNotAffectOriginal() {
140+
AnthropicChatOptions original = AnthropicChatOptions.builder()
141+
.model("original-model")
142+
.maxTokens(100)
143+
.temperature(0.5)
144+
.stopSequences(List.of("original-stop"))
145+
.toolContext(Map.of("original", "value"))
146+
.build();
147+
148+
AnthropicChatOptions copy = original.copy();
149+
copy.setModel("modified-model");
150+
copy.setMaxTokens(200);
151+
copy.setTemperature(0.8);
152+
153+
// Original should remain unchanged
154+
assertThat(original.getModel()).isEqualTo("original-model");
155+
assertThat(original.getMaxTokens()).isEqualTo(100);
156+
assertThat(original.getTemperature()).isEqualTo(0.5);
157+
158+
// Copy should have new values
159+
assertThat(copy.getModel()).isEqualTo("modified-model");
160+
assertThat(copy.getMaxTokens()).isEqualTo(200);
161+
assertThat(copy.getTemperature()).isEqualTo(0.8);
162+
}
163+
164+
@Test
165+
void testEqualsAndHashCode() {
166+
AnthropicChatOptions options1 = AnthropicChatOptions.builder()
167+
.model("test-model")
168+
.maxTokens(100)
169+
.temperature(0.7)
170+
.build();
171+
172+
AnthropicChatOptions options2 = AnthropicChatOptions.builder()
173+
.model("test-model")
174+
.maxTokens(100)
175+
.temperature(0.7)
176+
.build();
177+
178+
AnthropicChatOptions options3 = AnthropicChatOptions.builder()
179+
.model("different-model")
180+
.maxTokens(100)
181+
.temperature(0.7)
182+
.build();
183+
184+
assertThat(options1).isEqualTo(options2);
185+
assertThat(options1.hashCode()).isEqualTo(options2.hashCode());
186+
187+
assertThat(options1).isNotEqualTo(options3);
188+
assertThat(options1.hashCode()).isNotEqualTo(options3.hashCode());
189+
}
190+
191+
@Test
192+
void testChainedBuilderMethods() {
193+
AnthropicChatOptions options = AnthropicChatOptions.builder()
194+
.model("test-model")
195+
.maxTokens(150)
196+
.temperature(0.6)
197+
.topP(0.9)
198+
.topK(40)
199+
.stopSequences(List.of("stop"))
200+
.metadata(new Metadata("user_456"))
201+
.toolContext(Map.of("context", "value"))
202+
.build();
203+
204+
// Verify all chained methods worked
205+
assertThat(options.getModel()).isEqualTo("test-model");
206+
assertThat(options.getMaxTokens()).isEqualTo(150);
207+
assertThat(options.getTemperature()).isEqualTo(0.6);
208+
assertThat(options.getTopP()).isEqualTo(0.9);
209+
assertThat(options.getTopK()).isEqualTo(40);
210+
assertThat(options.getStopSequences()).containsExactly("stop");
211+
assertThat(options.getMetadata()).isEqualTo(new Metadata("user_456"));
212+
assertThat(options.getToolContext()).containsEntry("context", "value");
213+
}
214+
215+
@Test
216+
void testSettersWithNullValues() {
217+
AnthropicChatOptions options = new AnthropicChatOptions();
218+
219+
options.setModel(null);
220+
options.setMaxTokens(null);
221+
options.setTemperature(null);
222+
options.setTopK(null);
223+
options.setTopP(null);
224+
options.setStopSequences(null);
225+
options.setMetadata(null);
226+
options.setToolContext(null);
227+
228+
assertThat(options.getModel()).isNull();
229+
assertThat(options.getMaxTokens()).isNull();
230+
assertThat(options.getTemperature()).isNull();
231+
assertThat(options.getTopK()).isNull();
232+
assertThat(options.getTopP()).isNull();
233+
assertThat(options.getStopSequences()).isNull();
234+
assertThat(options.getMetadata()).isNull();
235+
assertThat(options.getToolContext()).isNull();
236+
}
237+
238+
@Test
239+
void testBuilderAndSetterConsistency() {
240+
// Build an object using builder
241+
AnthropicChatOptions builderOptions = AnthropicChatOptions.builder()
242+
.model("test-model")
243+
.maxTokens(100)
244+
.temperature(0.7)
245+
.topP(0.8)
246+
.topK(50)
247+
.build();
248+
249+
// Create equivalent object using setters
250+
AnthropicChatOptions setterOptions = new AnthropicChatOptions();
251+
setterOptions.setModel("test-model");
252+
setterOptions.setMaxTokens(100);
253+
setterOptions.setTemperature(0.7);
254+
setterOptions.setTopP(0.8);
255+
setterOptions.setTopK(50);
256+
257+
assertThat(builderOptions).isEqualTo(setterOptions);
258+
}
259+
260+
@Test
261+
void testMetadataEquality() {
262+
Metadata metadata1 = new Metadata("user_123");
263+
Metadata metadata2 = new Metadata("user_123");
264+
Metadata metadata3 = new Metadata("user_456");
265+
266+
AnthropicChatOptions options1 = AnthropicChatOptions.builder().metadata(metadata1).build();
267+
268+
AnthropicChatOptions options2 = AnthropicChatOptions.builder().metadata(metadata2).build();
269+
270+
AnthropicChatOptions options3 = AnthropicChatOptions.builder().metadata(metadata3).build();
271+
272+
assertThat(options1).isEqualTo(options2);
273+
assertThat(options1).isNotEqualTo(options3);
274+
}
275+
276+
@Test
277+
void testZeroValues() {
278+
AnthropicChatOptions options = AnthropicChatOptions.builder()
279+
.maxTokens(0)
280+
.temperature(0.0)
281+
.topP(0.0)
282+
.topK(0)
283+
.build();
284+
285+
assertThat(options.getMaxTokens()).isEqualTo(0);
286+
assertThat(options.getTemperature()).isEqualTo(0.0);
287+
assertThat(options.getTopP()).isEqualTo(0.0);
288+
assertThat(options.getTopK()).isEqualTo(0);
289+
}
290+
291+
@Test
292+
void testCopyPreservesAllFields() {
293+
AnthropicChatOptions original = AnthropicChatOptions.builder()
294+
.model("comprehensive-model")
295+
.maxTokens(500)
296+
.stopSequences(List.of("stop1", "stop2", "stop3"))
297+
.temperature(0.75)
298+
.topP(0.85)
299+
.topK(60)
300+
.metadata(new Metadata("comprehensive_test"))
301+
.toolContext(Map.of("key1", "value1", "key2", "value2"))
302+
.build();
303+
304+
AnthropicChatOptions copied = original.copy();
305+
306+
// Verify all fields are preserved
307+
assertThat(copied.getModel()).isEqualTo(original.getModel());
308+
assertThat(copied.getMaxTokens()).isEqualTo(original.getMaxTokens());
309+
assertThat(copied.getStopSequences()).isEqualTo(original.getStopSequences());
310+
assertThat(copied.getTemperature()).isEqualTo(original.getTemperature());
311+
assertThat(copied.getTopP()).isEqualTo(original.getTopP());
312+
assertThat(copied.getTopK()).isEqualTo(original.getTopK());
313+
assertThat(copied.getMetadata()).isEqualTo(original.getMetadata());
314+
assertThat(copied.getToolContext()).isEqualTo(original.getToolContext());
315+
316+
// Ensure deep copy for collections
317+
assertThat(copied.getStopSequences()).isNotSameAs(original.getStopSequences());
318+
assertThat(copied.getToolContext()).isNotSameAs(original.getToolContext());
319+
}
320+
104321
}

0 commit comments

Comments
 (0)