Skip to content

Commit a69b229

Browse files
alxkmWillam2004
authored andcommitted
Enhance OpenAiChatOptions test coverage (spring-projects#3959)
Tests Added - testEqualsAndHashCode() - equals/hashCode contract validation - testBuilderWithNullValues() - builder with null inputs - testBuilderChaining() - builder method chaining - testNullAndEmptyCollections() - null/empty collection handling - testStreamUsageStreamOptionsInteraction() - stream options state sync - testStopSequencesAlias() - stop/stopSequences field sync - testFromOptionsWithWebSearchOptionsNull() - fromOptions with null webSearch - testCopyChangeIndependence() - copy mutation independence validation Signed-off-by: Alex Klimenko <[email protected]> Signed-off-by: 家娃 <[email protected]>
1 parent 4389bd0 commit a69b229

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/OpenAiChatOptionsTests.java

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,173 @@ void testFromOptions_webSearchOptions() {
284284
assertThat(target.getWebSearchOptions().userLocation().approximate().timezone()).isEqualTo("UTC+8");
285285
}
286286

287+
@Test
288+
void testEqualsAndHashCode() {
289+
OpenAiChatOptions options1 = OpenAiChatOptions.builder()
290+
.model("test-model")
291+
.temperature(0.7)
292+
.maxTokens(100)
293+
.build();
294+
295+
OpenAiChatOptions options2 = OpenAiChatOptions.builder()
296+
.model("test-model")
297+
.temperature(0.7)
298+
.maxTokens(100)
299+
.build();
300+
301+
OpenAiChatOptions options3 = OpenAiChatOptions.builder()
302+
.model("different-model")
303+
.temperature(0.7)
304+
.maxTokens(100)
305+
.build();
306+
307+
// Test equals
308+
assertThat(options1).isEqualTo(options2);
309+
assertThat(options1).isNotEqualTo(options3);
310+
assertThat(options1).isNotEqualTo(null);
311+
assertThat(options1).isEqualTo(options1);
312+
313+
// Test hashCode
314+
assertThat(options1.hashCode()).isEqualTo(options2.hashCode());
315+
assertThat(options1.hashCode()).isNotEqualTo(options3.hashCode());
316+
}
317+
318+
@Test
319+
void testBuilderWithNullValues() {
320+
OpenAiChatOptions options = OpenAiChatOptions.builder()
321+
.temperature(null)
322+
.logitBias(null)
323+
.stop(null)
324+
.tools(null)
325+
.metadata(null)
326+
.build();
327+
328+
assertThat(options.getModel()).isNull();
329+
assertThat(options.getTemperature()).isNull();
330+
assertThat(options.getLogitBias()).isNull();
331+
assertThat(options.getStop()).isNull();
332+
assertThat(options.getTools()).isNull();
333+
assertThat(options.getMetadata()).isNull();
334+
}
335+
336+
@Test
337+
void testBuilderChaining() {
338+
OpenAiChatOptions.Builder builder = OpenAiChatOptions.builder();
339+
340+
OpenAiChatOptions.Builder result = builder.model("test-model").temperature(0.7).maxTokens(100);
341+
342+
assertThat(result).isSameAs(builder);
343+
344+
OpenAiChatOptions options = result.build();
345+
assertThat(options.getModel()).isEqualTo("test-model");
346+
assertThat(options.getTemperature()).isEqualTo(0.7);
347+
assertThat(options.getMaxTokens()).isEqualTo(100);
348+
}
349+
350+
@Test
351+
void testNullAndEmptyCollections() {
352+
OpenAiChatOptions options = new OpenAiChatOptions();
353+
354+
// Test setting null collections
355+
options.setLogitBias(null);
356+
options.setStop(null);
357+
options.setTools(null);
358+
options.setMetadata(null);
359+
options.setOutputModalities(null);
360+
361+
assertThat(options.getLogitBias()).isNull();
362+
assertThat(options.getStop()).isNull();
363+
assertThat(options.getTools()).isNull();
364+
assertThat(options.getMetadata()).isNull();
365+
assertThat(options.getOutputModalities()).isNull();
366+
367+
// Test setting empty collections
368+
options.setLogitBias(new HashMap<>());
369+
options.setStop(new ArrayList<>());
370+
options.setTools(new ArrayList<>());
371+
options.setMetadata(new HashMap<>());
372+
options.setOutputModalities(new ArrayList<>());
373+
374+
assertThat(options.getLogitBias()).isEmpty();
375+
assertThat(options.getStop()).isEmpty();
376+
assertThat(options.getTools()).isEmpty();
377+
assertThat(options.getMetadata()).isEmpty();
378+
assertThat(options.getOutputModalities()).isEmpty();
379+
}
380+
381+
@Test
382+
void testStreamUsageStreamOptionsInteraction() {
383+
OpenAiChatOptions options = new OpenAiChatOptions();
384+
385+
// Initially false
386+
assertThat(options.getStreamUsage()).isFalse();
387+
assertThat(options.getStreamOptions()).isNull();
388+
389+
// Setting streamUsage to true should set streamOptions
390+
options.setStreamUsage(true);
391+
assertThat(options.getStreamUsage()).isTrue();
392+
assertThat(options.getStreamOptions()).isEqualTo(StreamOptions.INCLUDE_USAGE);
393+
394+
// Setting streamUsage to false should clear streamOptions
395+
options.setStreamUsage(false);
396+
assertThat(options.getStreamUsage()).isFalse();
397+
assertThat(options.getStreamOptions()).isNull();
398+
399+
// Setting streamOptions directly should update streamUsage
400+
options.setStreamOptions(StreamOptions.INCLUDE_USAGE);
401+
assertThat(options.getStreamUsage()).isTrue();
402+
assertThat(options.getStreamOptions()).isEqualTo(StreamOptions.INCLUDE_USAGE);
403+
404+
// Setting streamOptions to null should set streamUsage to false
405+
options.setStreamOptions(null);
406+
assertThat(options.getStreamUsage()).isFalse();
407+
assertThat(options.getStreamOptions()).isNull();
408+
}
409+
410+
@Test
411+
void testStopSequencesAlias() {
412+
OpenAiChatOptions options = new OpenAiChatOptions();
413+
List<String> stopSequences = List.of("stop1", "stop2");
414+
415+
// Setting stopSequences should also set stop
416+
options.setStopSequences(stopSequences);
417+
assertThat(options.getStopSequences()).isEqualTo(stopSequences);
418+
assertThat(options.getStop()).isEqualTo(stopSequences);
419+
420+
// Setting stop should also update stopSequences
421+
List<String> newStop = List.of("stop3", "stop4");
422+
options.setStop(newStop);
423+
assertThat(options.getStop()).isEqualTo(newStop);
424+
assertThat(options.getStopSequences()).isEqualTo(newStop);
425+
}
426+
427+
@Test
428+
void testFromOptionsWithWebSearchOptionsNull() {
429+
OpenAiChatOptions source = OpenAiChatOptions.builder()
430+
.model("test-model")
431+
.temperature(0.7)
432+
.webSearchOptions(null)
433+
.build();
434+
435+
OpenAiChatOptions result = OpenAiChatOptions.fromOptions(source);
436+
assertThat(result.getModel()).isEqualTo("test-model");
437+
assertThat(result.getTemperature()).isEqualTo(0.7);
438+
assertThat(result.getWebSearchOptions()).isNull();
439+
}
440+
441+
@Test
442+
void testCopyChangeIndependence() {
443+
OpenAiChatOptions original = OpenAiChatOptions.builder().model("original-model").temperature(0.5).build();
444+
445+
OpenAiChatOptions copied = original.copy();
446+
447+
// Modify original
448+
original.setModel("modified-model");
449+
original.setTemperature(0.9);
450+
451+
// Verify copy is unchanged
452+
assertThat(copied.getModel()).isEqualTo("original-model");
453+
assertThat(copied.getTemperature()).isEqualTo(0.5);
454+
}
455+
287456
}

0 commit comments

Comments
 (0)