diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java index 3d09f769972..cb1ae58aa09 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java @@ -33,6 +33,7 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +45,7 @@ public class AnthropicChatAutoConfigurationIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)); @Test void call() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java index cdb00ee6af5..7a75e16efe3 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.anthropic.AnthropicChatModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -32,7 +33,7 @@ public class AnthropicModelConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)); @Test void chatModelActivation() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java index f87eb430dfe..7c84e132afa 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java @@ -21,6 +21,7 @@ import org.springframework.ai.anthropic.AnthropicChatModel; import org.springframework.ai.anthropic.api.AnthropicApi.ToolChoiceTool; import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -45,7 +46,7 @@ public void connectionProperties() { "spring.ai.anthropic.chat.options.model=MODEL_XYZ", "spring.ai.anthropic.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(AnthropicChatProperties.class); var connectionProperties = context.getBean(AnthropicConnectionProperties.class); @@ -81,7 +82,7 @@ public void chatOptionsTest() { "spring.ai.anthropic.chat.options.toolChoice={\"name\":\"toolChoiceFunctionName\",\"type\":\"tool\"}" ) // @formatter:on - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(AnthropicChatProperties.class); var connectionProperties = context.getBean(AnthropicConnectionProperties.class); @@ -109,7 +110,7 @@ public void chatCompletionDisabled() { // It is enabled by default new ApplicationContextRunner().withPropertyValues("spring.ai.anthropic.api-key=API_KEY") - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(AnthropicChatModel.class)).isNotEmpty(); @@ -118,7 +119,7 @@ public void chatCompletionDisabled() { // Explicitly enable the chat auto-configuration. new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.api-key=API_KEY", "spring.ai.model.chat=anthropic") - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(AnthropicChatModel.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java deleted file mode 100644 index c68d9188e10..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.anthropic.autoconfigure; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; - -public abstract class BaseAnthropicIT { - - public static AutoConfigurations anthropicAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class, - RestClientAutoConfiguration.class, WebClientAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java index 1c34450d84a..03cf82807b6 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java @@ -31,10 +31,10 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; -import org.springframework.ai.model.anthropic.autoconfigure.BaseAnthropicIT; import org.springframework.ai.model.anthropic.autoconfigure.tool.MockWeatherService.Request; import org.springframework.ai.model.anthropic.autoconfigure.tool.MockWeatherService.Response; import org.springframework.ai.model.tool.ToolCallingChatOptions; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -49,7 +49,7 @@ class FunctionCallWithFunctionBeanIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java index 50e336aa162..e790eb46b72 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java @@ -30,8 +30,8 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; -import org.springframework.ai.model.anthropic.autoconfigure.BaseAnthropicIT; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -43,7 +43,7 @@ public class FunctionCallWithPromptFunctionIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(AnthropicChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationEntraIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationEntraIT.java index 21a544984f4..fac97ab1aec 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationEntraIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationEntraIT.java @@ -49,8 +49,7 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -63,6 +62,7 @@ * @author Piotr Olaszewski * @author Soby Chacko * @author Manuel Andreo Garcia + * @author Issam El-atif * @since 0.8.0 */ @DisabledIfEnvironmentVariable(named = "AZURE_OPENAI_API_KEY", matches = ".+") @@ -99,9 +99,7 @@ class AzureOpenAiAutoConfigurationEntraIT { @Test void chatCompletion() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { AzureOpenAiChatModel chatModel = context.getBean(AzureOpenAiChatModel.class); ChatResponse response = chatModel.call(new Prompt(List.of(this.userMessage, this.systemMessage))); @@ -111,9 +109,7 @@ void chatCompletion() { @Test void httpRequestContainsUserAgentAndCustomHeaders() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.azure.openai.custom-headers.foo=bar", "spring.ai.azure.openai.custom-headers.fizz=buzz") .run(context -> { @@ -140,9 +136,7 @@ void httpRequestContainsUserAgentAndCustomHeaders() { @Test void chatCompletionStreaming() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { AzureOpenAiChatModel chatModel = context.getBean(AzureOpenAiChatModel.class); @@ -167,8 +161,7 @@ void chatCompletionStreaming() { @Test void embedding() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { AzureOpenAiEmbeddingModel embeddingModel = context.getBean(AzureOpenAiEmbeddingModel.class); @@ -189,8 +182,7 @@ void embedding() { @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_TRANSCRIPTION_DEPLOYMENT_NAME", matches = ".+") void transcribe() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { AzureOpenAiAudioTranscriptionModel transcriptionModel = context .getBean(AzureOpenAiAudioTranscriptionModel.class); @@ -205,9 +197,7 @@ void transcribe() { void chatActivation() { // Disable the chat auto-configuration. - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isEmpty(); @@ -215,18 +205,14 @@ void chatActivation() { }); // The chat auto-configuration is enabled by default. - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isNotEmpty(); }); // Explicitly enable the chat auto-configuration. - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty(); @@ -239,8 +225,7 @@ void embeddingActivation() { // Disable the embedding auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty(); @@ -249,8 +234,7 @@ void embeddingActivation() { // The embedding auto-configuration is enabled by default. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(AzureOpenAiEmbeddingProperties.class)).isNotEmpty(); @@ -258,8 +242,7 @@ void embeddingActivation() { // Explicitly enable the embedding auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty(); @@ -272,8 +255,7 @@ void audioTranscriptionActivation() { // Disable the transcription auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty(); @@ -282,14 +264,12 @@ void audioTranscriptionActivation() { // The transcription auto-configuration is enabled by default. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty()); // Explicitly enable the transcription auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=azure-openai") .run(context -> assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty()); } @@ -298,9 +278,7 @@ void audioTranscriptionActivation() { void openAIClientBuilderCustomizer() { AtomicBoolean firstCustomizationApplied = new AtomicBoolean(false); AtomicBoolean secondCustomizationApplied = new AtomicBoolean(false); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withBean("first", AzureOpenAIClientBuilderCustomizer.class, () -> clientBuilder -> firstCustomizationApplied.set(true)) .withBean("second", AzureOpenAIClientBuilderCustomizer.class, diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationIT.java index 99647314ad0..b065b47d1fc 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationIT.java @@ -47,8 +47,7 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -61,6 +60,7 @@ * @author Piotr Olaszewski * @author Soby Chacko * @author Manuel Andreo Garcia + * @author Issam El-atif * @since 0.8.0 */ @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_API_KEY", matches = ".+") @@ -97,9 +97,7 @@ class AzureOpenAiAutoConfigurationIT { @Test void chatCompletion() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { AzureOpenAiChatModel chatModel = context.getBean(AzureOpenAiChatModel.class); ChatResponse response = chatModel.call(new Prompt(List.of(this.userMessage, this.systemMessage))); @@ -109,9 +107,7 @@ void chatCompletion() { @Test void httpRequestContainsUserAgentAndCustomHeaders() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.azure.openai.custom-headers.foo=bar", "spring.ai.azure.openai.custom-headers.fizz=buzz") .run(context -> { @@ -138,9 +134,7 @@ void httpRequestContainsUserAgentAndCustomHeaders() { @Test void chatCompletionStreaming() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { AzureOpenAiChatModel chatModel = context.getBean(AzureOpenAiChatModel.class); @@ -165,8 +159,7 @@ void chatCompletionStreaming() { @Test void embedding() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { AzureOpenAiEmbeddingModel embeddingModel = context.getBean(AzureOpenAiEmbeddingModel.class); @@ -187,8 +180,7 @@ void embedding() { @EnabledIfEnvironmentVariable(named = "AZURE_OPENAI_TRANSCRIPTION_DEPLOYMENT_NAME", matches = ".+") void transcribe() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { AzureOpenAiAudioTranscriptionModel transcriptionModel = context .getBean(AzureOpenAiAudioTranscriptionModel.class); @@ -203,9 +195,7 @@ void transcribe() { void chatActivation() { // Disable the chat auto-configuration. - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isEmpty(); @@ -213,18 +203,14 @@ void chatActivation() { }); // The chat auto-configuration is enabled by default. - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isNotEmpty(); }); // Explicitly enable the chat auto-configuration. - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty(); @@ -237,8 +223,7 @@ void embeddingActivation() { // Disable the embedding auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty(); @@ -247,8 +232,7 @@ void embeddingActivation() { // The embedding auto-configuration is enabled by default. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(AzureOpenAiEmbeddingProperties.class)).isNotEmpty(); @@ -256,8 +240,7 @@ void embeddingActivation() { // Explicitly enable the embedding auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty(); @@ -270,8 +253,7 @@ void audioTranscriptionActivation() { // Disable the transcription auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty(); @@ -280,14 +262,12 @@ void audioTranscriptionActivation() { // The transcription auto-configuration is enabled by default. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty()); // Explicitly enable the transcription auto-configuration. this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=azure-openai") .run(context -> assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isNotEmpty()); } @@ -296,9 +276,7 @@ void audioTranscriptionActivation() { void openAIClientBuilderCustomizer() { AtomicBoolean firstCustomizationApplied = new AtomicBoolean(false); AtomicBoolean secondCustomizationApplied = new AtomicBoolean(false); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withBean("first", AzureOpenAIClientBuilderCustomizer.class, () -> clientBuilder -> firstCustomizationApplied.set(true)) .withBean("second", AzureOpenAIClientBuilderCustomizer.class, diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationPropertyTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationPropertyTests.java index f327b4df3cd..99a1b190187 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationPropertyTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiAutoConfigurationPropertyTests.java @@ -18,14 +18,14 @@ import org.junit.jupiter.api.Test; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; /** * @author Christian Tzolov + * @author Issam El-atif * @since 0.8.0 */ public class AzureOpenAiAutoConfigurationPropertyTests { @@ -37,8 +37,7 @@ public void embeddingPropertiesTest() { .withPropertyValues("spring.ai.azure.openai.api-key=TEST_API_KEY", "spring.ai.azure.openai.endpoint=TEST_ENDPOINT", "spring.ai.azure.openai.embedding.options.deployment-name=MODEL_XYZ") - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(AzureOpenAiEmbeddingProperties.class); var connectionProperties = context.getBean(AzureOpenAiConnectionProperties.class); @@ -70,8 +69,8 @@ public void chatPropertiesTest() { "spring.ai.azure.openai.chat.options.user=userXYZ" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiChatAutoConfiguration.class, AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class, + AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(AzureOpenAiChatProperties.class); var connectionProperties = context.getBean(AzureOpenAiConnectionProperties.class); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiDirectOpenAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiDirectOpenAiAutoConfigurationIT.java index 130a9b37743..81eb1bcd7ea 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiDirectOpenAiAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiDirectOpenAiAutoConfigurationIT.java @@ -34,14 +34,14 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; /** * @author Christian Tzolov + * @author Issam El-atif * @since 1.0.0 */ @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".*") @@ -61,8 +61,8 @@ public class AzureOpenAiDirectOpenAiAutoConfigurationIT { "spring.ai.azure.openai.embedding.options.deployment-name=" + EMBEDDING_MODEL_NAME // @formatter:on ) - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiChatAutoConfiguration.class, AzureOpenAiEmbeddingAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class, + AzureOpenAiEmbeddingAutoConfiguration.class)); private final Message systemMessage = new SystemPromptTemplate(""" You are a helpful AI assistant. Your name is {name}. diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiModelConfigurationTests.java index 7f22a0162cd..9e041202619 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/AzureOpenAiModelConfigurationTests.java @@ -24,8 +24,7 @@ import org.springframework.ai.azure.openai.AzureOpenAiChatModel; import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel; import org.springframework.ai.azure.openai.AzureOpenAiImageModel; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -34,6 +33,7 @@ * Unit Tests for Azure OpenAI auto-configurations conditional enabling of models. * * @author Ilayaperumal Gopinathan + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".*") public class AzureOpenAiModelConfigurationTests { @@ -44,9 +44,7 @@ public class AzureOpenAiModelConfigurationTests { @Test void chatModelActivation() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty(); @@ -55,9 +53,7 @@ void chatModelActivation() { assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty(); }); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isEmpty(); @@ -65,18 +61,14 @@ void chatModelActivation() { assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isEmpty(); }); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isNotEmpty(); }); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=azure-openai", "spring.ai.model.embedding=none", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -92,8 +84,7 @@ void chatModelActivation() { @Test void embeddingModelActivation() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isNotEmpty(); @@ -103,8 +94,7 @@ void embeddingModelActivation() { }); this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingProperties.class)).isEmpty(); @@ -113,8 +103,7 @@ void embeddingModelActivation() { }); this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiEmbeddingProperties.class)).isNotEmpty(); @@ -123,8 +112,7 @@ void embeddingModelActivation() { }); this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=azure-openai", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -139,9 +127,7 @@ void embeddingModelActivation() { @Test void imageModelActivation() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty(); @@ -150,9 +136,7 @@ void imageModelActivation() { assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionModel.class)).isEmpty(); }); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiImageAutoConfiguration.class)) .withPropertyValues("spring.ai.model.image=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiImageOptionsProperties.class)).isEmpty(); @@ -160,9 +144,7 @@ void imageModelActivation() { assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isEmpty(); }); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiImageAutoConfiguration.class)) .withPropertyValues("spring.ai.model.image=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiImageOptionsProperties.class)).isNotEmpty(); @@ -170,9 +152,7 @@ void imageModelActivation() { assertThat(context.getBeansOfType(OpenAIClientBuilder.class)).isNotEmpty(); }); - this.contextRunner - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiImageAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.image=azure-openai", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -188,8 +168,7 @@ void imageModelActivation() { @Test void audioTranscriptionModelActivation() { this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(AzureOpenAiEmbeddingModel.class)).isEmpty(); @@ -199,8 +178,7 @@ void audioTranscriptionModelActivation() { }); this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=none") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionProperties.class)).isEmpty(); @@ -209,8 +187,7 @@ void audioTranscriptionModelActivation() { }); this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=azure-openai") .run(context -> { assertThat(context.getBeansOfType(AzureOpenAiAudioTranscriptionProperties.class)).isNotEmpty(); @@ -219,8 +196,7 @@ void audioTranscriptionModelActivation() { }); this.contextRunner - .withConfiguration(AutoConfigurations.of(ToolCallingAutoConfiguration.class, - AzureOpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=azure-openai", "spring.ai.model.moderation=none") diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java index e19f1bb7b72..37ab46292a9 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java @@ -32,8 +32,7 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; import org.springframework.ai.model.tool.ToolCallingChatOptions; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -52,8 +51,7 @@ class FunctionCallWithFunctionBeanIT { "spring.ai.azure.openai.api-key=" + System.getenv("AZURE_OPENAI_API_KEY"), "spring.ai.azure.openai.endpoint=" + System.getenv("AZURE_OPENAI_ENDPOINT")) // @formatter:on - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionWrapperIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionWrapperIT.java index e7d63d042fd..1c6ddf8f184 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionWrapperIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithFunctionWrapperIT.java @@ -29,10 +29,9 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -50,8 +49,7 @@ public class FunctionCallWithFunctionWrapperIT { "spring.ai.azure.openai.api-key=" + System.getenv("AZURE_OPENAI_API_KEY"), "spring.ai.azure.openai.endpoint=" + System.getenv("AZURE_OPENAI_ENDPOINT")) // @formatter:on - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java index 25c4ad24038..cdd909cfc2a 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-azure-openai/src/test/java/org/springframework/ai/model/azure/openai/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java @@ -29,9 +29,8 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -47,8 +46,7 @@ public class FunctionCallWithPromptFunctionIT { "spring.ai.azure.openai.api-key=" + System.getenv("AZURE_OPENAI_API_KEY"), "spring.ai.azure.openai.endpoint=" + System.getenv("AZURE_OPENAI_ENDPOINT")) // @formatter:on - .withConfiguration( - AutoConfigurations.of(ToolCallingAutoConfiguration.class, AzureOpenAiChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(AzureOpenAiChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseModelConfigurationTests.java index 2559231fd78..573b2d68e87 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseModelConfigurationTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.bedrock.converse.BedrockProxyChatModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -29,11 +30,12 @@ * * @author Ilayaperumal Gopinathan * @author Pawel Potaczala + * @author Issam El-atif */ public class BedrockConverseModelConfigurationTests { - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( - BedrockConverseProxyITUtil.bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)); + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)); @Test void chatModelActivation() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatAutoConfigurationIT.java index 22460ab9296..a0bb81310e4 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatAutoConfigurationIT.java @@ -32,6 +32,7 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.bedrock.autoconfigure.BedrockTestUtils; import org.springframework.ai.model.bedrock.autoconfigure.RequiresAwsCredentials; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -45,8 +46,7 @@ public class BedrockConverseProxyChatAutoConfigurationIT { .withPropertyValues( "spring.ai.bedrock.converse.chat.options.model=" + "anthropic.claude-3-5-sonnet-20240620-v1:0", "spring.ai.bedrock.converse.chat.options.temperature=0.5") - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)); @Test void call() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatPropertiesTests.java index 196d16f83e3..46d24a01d24 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatPropertiesTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.bedrock.converse.BedrockProxyChatModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -26,6 +27,7 @@ /** * @author Christian Tzolov * @author Pawel Potaczala + * @author Issam El-atif * * Unit Tests for {@link BedrockConverseProxyChatProperties}. */ @@ -47,8 +49,7 @@ public void chatOptionsTest() { "spring.ai.bedrock.converse.chat.options.top-k=100" ) // @formatter:on - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(BedrockConverseProxyChatProperties.class); @@ -67,14 +68,12 @@ public void chatCompletionDisabled() { // It is enabled by default new ApplicationContextRunner() - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)) .run(context -> assertThat(context.getBeansOfType(BedrockConverseProxyChatProperties.class)).isNotEmpty()); // Explicitly enable the chat auto-configuration. new ApplicationContextRunner().withPropertyValues("spring.ai.model.chat=bedrock-converse") - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockConverseProxyChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(BedrockProxyChatModel.class)).isNotEmpty(); @@ -82,8 +81,7 @@ public void chatCompletionDisabled() { // Explicitly disable the chat auto-configuration. new ApplicationContextRunner().withPropertyValues("spring.ai.model.chat=none") - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(BedrockConverseProxyChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(BedrockProxyChatModel.class)).isEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyITUtil.java b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyITUtil.java deleted file mode 100644 index d055d2ef2df..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyITUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.bedrock.converse.autoconfigure; - -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; - -/** - * Utility class for Bedrock Converse Proxy integration tests. - * - * @author Pawel Potaczala - */ -public final class BedrockConverseProxyITUtil { - - private BedrockConverseProxyITUtil() { - } - - public static AutoConfigurations bedrockConverseProxyAutoConfig(Class... additionalAutoConfigurations) { - Class[] dependencies = new Class[] { ToolCallingAutoConfiguration.class }; - Class[] allAutoConfigurations = new Class[dependencies.length + additionalAutoConfigurations.length]; - System.arraycopy(dependencies, 0, allAutoConfigurations, 0, dependencies.length); - System.arraycopy(additionalAutoConfigurations, 0, allAutoConfigurations, dependencies.length, - additionalAutoConfigurations.length); - - return AutoConfigurations.of(allAutoConfigurations); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java index da5fdf27cfc..968b2b32640 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java @@ -33,7 +33,7 @@ import org.springframework.ai.model.bedrock.autoconfigure.BedrockTestUtils; import org.springframework.ai.model.bedrock.autoconfigure.RequiresAwsCredentials; import org.springframework.ai.model.bedrock.converse.autoconfigure.BedrockConverseProxyChatAutoConfiguration; -import org.springframework.ai.model.bedrock.converse.autoconfigure.BedrockConverseProxyITUtil; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -47,8 +47,7 @@ class FunctionCallWithFunctionBeanIT { private final Logger logger = LoggerFactory.getLogger(FunctionCallWithFunctionBeanIT.class); private final ApplicationContextRunner contextRunner = BedrockTestUtils.getContextRunner() - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java index a959d362ef7..9cdb6740717 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java @@ -30,8 +30,8 @@ import org.springframework.ai.model.bedrock.autoconfigure.BedrockTestUtils; import org.springframework.ai.model.bedrock.autoconfigure.RequiresAwsCredentials; import org.springframework.ai.model.bedrock.converse.autoconfigure.BedrockConverseProxyChatAutoConfiguration; -import org.springframework.ai.model.bedrock.converse.autoconfigure.BedrockConverseProxyITUtil; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -42,8 +42,7 @@ public class FunctionCallWithPromptFunctionIT { private final Logger logger = LoggerFactory.getLogger(FunctionCallWithPromptFunctionIT.class); private final ApplicationContextRunner contextRunner = BedrockTestUtils.getContextRunner() - .withConfiguration(BedrockConverseProxyITUtil - .bedrockConverseProxyAutoConfig(BedrockConverseProxyChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java deleted file mode 100644 index 9423542a624..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.deepseek.autoconfigure; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; - -/** - * Base utility class for DeepSeek integration tests. - * - * @author Hyunsang Han - */ -public abstract class BaseDeepSeekIT { - - public static AutoConfigurations deepSeekAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class, - RestClientAutoConfiguration.class, WebClientAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekAutoConfigurationIT.java index 0e0c49f6e8a..94db5f43bd3 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekAutoConfigurationIT.java @@ -29,6 +29,7 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -36,15 +37,16 @@ /** * @author Geng Rong * @author Hyunsang Han + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*") -public class DeepSeekAutoConfigurationIT extends BaseDeepSeekIT { +public class DeepSeekAutoConfigurationIT { private static final Log logger = LogFactory.getLog(DeepSeekAutoConfigurationIT.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY")) - .withConfiguration(BaseDeepSeekIT.deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)); @Test void generate() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekPropertiesTests.java index 6d88c4e2688..e126ba67aba 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekPropertiesTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -26,8 +27,9 @@ /** * @author Geng Rong * @author Hyunsang Han + * @author Issam El-atif */ -public class DeepSeekPropertiesTests extends BaseDeepSeekIT { +public class DeepSeekPropertiesTests { @Test public void chatProperties() { @@ -39,7 +41,7 @@ public void chatProperties() { "spring.ai.deepseek.chat.options.model=MODEL_XYZ", "spring.ai.deepseek.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(DeepSeekChatProperties.class); var connectionProperties = context.getBean(DeepSeekConnectionProperties.class); @@ -67,7 +69,7 @@ public void chatOverrideConnectionProperties() { "spring.ai.deepseek.chat.options.model=MODEL_XYZ", "spring.ai.deepseek.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(DeepSeekChatProperties.class); var connectionProperties = context.getBean(DeepSeekConnectionProperties.class); @@ -104,7 +106,7 @@ public void chatOptionsTest() { "spring.ai.deepseek.chat.options.user=userXYZ" ) // @formatter:on - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(DeepSeekChatProperties.class); var connectionProperties = context.getBean(DeepSeekConnectionProperties.class); @@ -127,7 +129,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.api-key=API_KEY", "spring.ai.deepseek.base-url=TEST_BASE_URL", "spring.ai.model.chat=none") - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(DeepSeekChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(DeepSeekChatModel.class)).isEmpty(); @@ -135,7 +137,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.api-key=API_KEY", "spring.ai.deepseek.base-url=TEST_BASE_URL") - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(DeepSeekChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(DeepSeekChatModel.class)).isNotEmpty(); @@ -144,7 +146,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.api-key=API_KEY", "spring.ai.deepseek.base-url=TEST_BASE_URL", "spring.ai.model.chat=deepseek") - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(DeepSeekChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(DeepSeekChatModel.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/DeepSeekFunctionCallbackIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/DeepSeekFunctionCallbackIT.java index 3d2e63c4f84..58f59e14828 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/DeepSeekFunctionCallbackIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/DeepSeekFunctionCallbackIT.java @@ -33,10 +33,10 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.deepseek.DeepSeekChatModel; import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.model.deepseek.autoconfigure.BaseDeepSeekIT; import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -46,17 +46,18 @@ /** * @author Geng Rong * @author Hyunsang Han + * @author Issam El-atif */ // @Disabled("the deepseek-chat model's Function Calling capability is unstable see: // https://api-docs.deepseek.com/guides/function_calling") @EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*") -public class DeepSeekFunctionCallbackIT extends BaseDeepSeekIT { +public class DeepSeekFunctionCallbackIT { private final Logger logger = LoggerFactory.getLogger(DeepSeekFunctionCallbackIT.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY")) - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackInPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackInPromptIT.java index 4ae85f607e8..4783b85a116 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackInPromptIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackInPromptIT.java @@ -32,9 +32,9 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.deepseek.DeepSeekChatModel; import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.model.deepseek.autoconfigure.BaseDeepSeekIT; import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -42,17 +42,18 @@ /** * @author Geng Rong * @author Hyunsang Han + * @author Issam El-atif */ // @Disabled("the deepseek-chat model's Function Calling capability is unstable see: // https://api-docs.deepseek.com/guides/function_calling") @EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*") -public class FunctionCallbackInPromptIT extends BaseDeepSeekIT { +public class FunctionCallbackInPromptIT { private final Logger logger = LoggerFactory.getLogger(FunctionCallbackInPromptIT.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY")) - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java index 0d97934ae66..8aed315143a 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java @@ -33,9 +33,9 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.deepseek.DeepSeekChatModel; import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.model.deepseek.autoconfigure.BaseDeepSeekIT; import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; import org.springframework.ai.model.tool.ToolCallingChatOptions; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -46,17 +46,18 @@ /** * @author Geng Rong * @author Hyunsang Han + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*") // @Disabled("the deepseek-chat model's Function Calling capability is unstable see: // https://api-docs.deepseek.com/guides/function_calling") -class FunctionCallbackWithPlainFunctionBeanIT extends BaseDeepSeekIT { +class FunctionCallbackWithPlainFunctionBeanIT { private final Logger logger = LoggerFactory.getLogger(FunctionCallbackWithPlainFunctionBeanIT.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY")) - .withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(DeepSeekChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfigurationIT.java index 493a8d17441..3ed45ca9867 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfigurationIT.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.elevenlabs.ElevenLabsTextToSpeechModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -30,6 +31,7 @@ * Integration tests for the {@link ElevenLabsAutoConfiguration}. * * @author Alexandros Pappas + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "ELEVEN_LABS_API_KEY", matches = ".*") public class ElevenLabsAutoConfigurationIT { @@ -39,7 +41,7 @@ public class ElevenLabsAutoConfigurationIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.elevenlabs.api-key=" + System.getenv("ELEVEN_LABS_API_KEY")) - .withConfiguration(ElevenLabsITUtil.elevenLabsAutoConfig(ElevenLabsAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(ElevenLabsAutoConfiguration.class)); @Test void speech() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java deleted file mode 100644 index 9cd2b178856..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.elevenlabs.autoconfigure; - -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; - -/** - * Utility class for ElevenLabs integration tests. - * - * @author Pawel Potaczala - */ -public final class ElevenLabsITUtil { - - private ElevenLabsITUtil() { - } - - public static AutoConfigurations elevenLabsAutoConfig(Class... additionalAutoConfigurations) { - Class[] dependencies = new Class[] { SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - WebClientAutoConfiguration.class }; - Class[] allAutoConfigurations = new Class[dependencies.length + additionalAutoConfigurations.length]; - System.arraycopy(dependencies, 0, allAutoConfigurations, 0, dependencies.length); - System.arraycopy(additionalAutoConfigurations, 0, allAutoConfigurations, dependencies.length, - additionalAutoConfigurations.length); - - return AutoConfigurations.of(allAutoConfigurations); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsPropertiesTests.java index e3aa6555d9f..08b5f6e4c38 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsPropertiesTests.java @@ -20,6 +20,7 @@ import org.springframework.ai.elevenlabs.ElevenLabsTextToSpeechModel; import org.springframework.ai.elevenlabs.api.ElevenLabsApi; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -29,6 +30,7 @@ * {@link ElevenLabsConnectionProperties}. * * @author Alexandros Pappas + * @author Issam El-atif */ public class ElevenLabsPropertiesTests { @@ -46,7 +48,7 @@ public void connectionProperties() { "spring.ai.elevenlabs.tts.options.voice-settings.use-speaker-boost=false", "spring.ai.elevenlabs.tts.options.voice-settings.speed=1.5" // @formatter:on - ).withConfiguration(ElevenLabsITUtil.elevenLabsAutoConfig(ElevenLabsAutoConfiguration.class)).run(context -> { + ).withConfiguration(SpringAiTestAutoConfigurations.of(ElevenLabsAutoConfiguration.class)).run(context -> { var speechProperties = context.getBean(ElevenLabsSpeechProperties.class); var connectionProperties = context.getBean(ElevenLabsConnectionProperties.class); @@ -86,7 +88,7 @@ public void speechOptionsTest() { "spring.ai.elevenlabs.tts.options.apply-text-normalization=ON", "spring.ai.elevenlabs.tts.options.apply-language-text-normalization=true" // @formatter:on - ).withConfiguration(ElevenLabsITUtil.elevenLabsAutoConfig(ElevenLabsAutoConfiguration.class)).run(context -> { + ).withConfiguration(SpringAiTestAutoConfigurations.of(ElevenLabsAutoConfiguration.class)).run(context -> { var speechProperties = context.getBean(ElevenLabsSpeechProperties.class); assertThat(speechProperties.getOptions().getModelId()).isEqualTo("custom-model"); @@ -113,7 +115,7 @@ public void speechActivation() { // It is enabled by default new ApplicationContextRunner().withPropertyValues("spring.ai.elevenlabs.api-key=YOUR_API_KEY") - .withConfiguration(ElevenLabsITUtil.elevenLabsAutoConfig(ElevenLabsAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ElevenLabsAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ElevenLabsSpeechProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ElevenLabsTextToSpeechModel.class)).isNotEmpty(); @@ -122,7 +124,7 @@ public void speechActivation() { // Explicitly enable the text-to-speech autoconfiguration. new ApplicationContextRunner() .withPropertyValues("spring.ai.elevenlabs.api-key=YOUR_API_KEY", "spring.ai.elevenlabs.tts.enabled=true") - .withConfiguration(ElevenLabsITUtil.elevenLabsAutoConfig(ElevenLabsAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ElevenLabsAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ElevenLabsSpeechProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ElevenLabsTextToSpeechModel.class)).isNotEmpty(); @@ -131,7 +133,7 @@ public void speechActivation() { // Explicitly disable the text-to-speech autoconfiguration. new ApplicationContextRunner() .withPropertyValues("spring.ai.elevenlabs.api-key=YOUR_API_KEY", "spring.ai.elevenlabs.tts.enabled=false") - .withConfiguration(ElevenLabsITUtil.elevenLabsAutoConfig(ElevenLabsAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ElevenLabsAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ElevenLabsSpeechProperties.class)).isEmpty(); assertThat(context.getBeansOfType(ElevenLabsTextToSpeechModel.class)).isEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/BaseGoogleGenAiIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/BaseGoogleGenAiIT.java deleted file mode 100644 index a80a41944a9..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/BaseGoogleGenAiIT.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.google.genai.autoconfigure; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration; -import org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiEmbeddingConnectionAutoConfiguration; -import org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiTextEmbeddingAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; - -/** - * Base class to provide consistent AutoConfigurations for Google GenAI integration tests. - */ -public abstract class BaseGoogleGenAiIT { - - /** - * AutoConfigurations needed for Google GenAI Chat model. - */ - public static AutoConfigurations googleGenAiChatAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class, - GoogleGenAiChatAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - - /** - * AutoConfigurations needed for Google GenAI Text Embedding model. - */ - public static AutoConfigurations googleGenAiEmbeddingAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, - GoogleGenAiEmbeddingConnectionAutoConfiguration.class, - GoogleGenAiTextEmbeddingAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiCachedContentServiceAutoConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiCachedContentServiceAutoConfigurationTests.java index ee306d0dcc7..3c53e31c868 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiCachedContentServiceAutoConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiCachedContentServiceAutoConfigurationTests.java @@ -22,8 +22,8 @@ import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.cache.GoogleGenAiCachedContentService; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; import org.springframework.ai.model.tool.ToolCallingManager; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,12 +35,13 @@ * Integration tests for Google GenAI Cached Content Service auto-configuration. * * @author Dan Dobrin + * @author Issam El-atif * @since 1.1.0 */ public class GoogleGenAiCachedContentServiceAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); @Test void cachedContentServiceBeanIsCreatedWhenChatModelExists() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfigurationIT.java index 7532c543571..f4a42651661 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfigurationIT.java @@ -28,7 +28,7 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.google.genai.GoogleGenAiChatModel; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -49,7 +49,7 @@ public class GoogleGenAiChatAutoConfigurationIT { void generateWithApiKey() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.api-key=" + System.getenv("GOOGLE_API_KEY")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { GoogleGenAiChatModel chatModel = context.getBean(GoogleGenAiChatModel.class); @@ -64,7 +64,7 @@ void generateWithApiKey() { void generateStreamingWithApiKey() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.api-key=" + System.getenv("GOOGLE_API_KEY")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { GoogleGenAiChatModel chatModel = context.getBean(GoogleGenAiChatModel.class); @@ -87,7 +87,7 @@ void generateWithVertexAi() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.project-id=" + System.getenv("GOOGLE_CLOUD_PROJECT"), "spring.ai.google.genai.location=" + System.getenv("GOOGLE_CLOUD_LOCATION")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { GoogleGenAiChatModel chatModel = context.getBean(GoogleGenAiChatModel.class); @@ -104,7 +104,7 @@ void generateStreamingWithVertexAi() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.project-id=" + System.getenv("GOOGLE_CLOUD_PROJECT"), "spring.ai.google.genai.location=" + System.getenv("GOOGLE_CLOUD_LOCATION")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { GoogleGenAiChatModel chatModel = context.getBean(GoogleGenAiChatModel.class); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiModelConfigurationTests.java index 25e9844257c..d58c6123b7b 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiModelConfigurationTests.java @@ -20,7 +20,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.google.genai.GoogleGenAiChatModel; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -29,6 +29,7 @@ * Unit Tests for Google GenAI auto configurations' conditional enabling of models. * * @author Ilayaperumal Gopinathan + * @author Issam El-atif */ class GoogleGenAiModelConfigurationTests { @@ -37,14 +38,14 @@ class GoogleGenAiModelConfigurationTests { @Test void chatModelActivationWithApiKey() { - this.contextRunner.withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.google.genai.api-key=test-key", "spring.ai.model.chat=none") .run(context -> { assertThat(context.getBeansOfType(GoogleGenAiChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(GoogleGenAiChatModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.google.genai.api-key=test-key", "spring.ai.model.chat=google-genai") .run(context -> { assertThat(context.getBeansOfType(GoogleGenAiChatProperties.class)).isNotEmpty(); @@ -57,7 +58,7 @@ void chatModelActivationWithApiKey() { @EnabledIfEnvironmentVariable(named = "GOOGLE_CLOUD_LOCATION", matches = ".*") void chatModelActivationWithVertexAi() { - this.contextRunner.withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.google.genai.project-id=test-project", "spring.ai.google.genai.location=us-central1", "spring.ai.model.chat=none") .run(context -> { @@ -65,7 +66,7 @@ void chatModelActivationWithVertexAi() { assertThat(context.getBeansOfType(GoogleGenAiChatModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.google.genai.project-id=test-project", "spring.ai.google.genai.location=us-central1", "spring.ai.model.chat=google-genai") .run(context -> { @@ -78,7 +79,7 @@ void chatModelActivationWithVertexAi() { void chatModelDefaultActivation() { // Tests that the model is activated by default when spring.ai.model.chat is not // set - this.contextRunner.withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.google.genai.api-key=test-key") .run(context -> { assertThat(context.getBeansOfType(GoogleGenAiChatProperties.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java index 328e742fcfa..cf8984428c6 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java @@ -27,9 +27,10 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; +import org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; @@ -51,7 +52,8 @@ public class FunctionCallWithFunctionBeanIT { void functionCallWithApiKey() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.api-key=" + System.getenv("GOOGLE_API_KEY")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig(RestClientAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class, + RestClientAutoConfiguration.class)) .withUserConfiguration(FunctionConfiguration.class); contextRunner.run(context -> { @@ -81,7 +83,8 @@ void functionCallWithVertexAi() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.project-id=" + System.getenv("GOOGLE_CLOUD_PROJECT"), "spring.ai.google.genai.location=" + System.getenv("GOOGLE_CLOUD_LOCATION")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig(RestClientAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class, + RestClientAutoConfiguration.class)) .withUserConfiguration(FunctionConfiguration.class); contextRunner.run(context -> { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionWrapperIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionWrapperIT.java index ad39063677b..d7954d1149f 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionWrapperIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionWrapperIT.java @@ -29,9 +29,10 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; +import org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -49,7 +50,7 @@ public class FunctionCallWithFunctionWrapperIT { void functionCallWithApiKey() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.api-key=" + System.getenv("GOOGLE_API_KEY")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { @@ -86,7 +87,7 @@ void functionCallWithVertexAi() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.project-id=" + System.getenv("GOOGLE_CLOUD_PROJECT"), "spring.ai.google.genai.location=" + System.getenv("GOOGLE_CLOUD_LOCATION")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithPromptFunctionIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithPromptFunctionIT.java index 208b1eccae0..e93586729b3 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithPromptFunctionIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithPromptFunctionIT.java @@ -28,8 +28,9 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.google.genai.GoogleGenAiChatModel; import org.springframework.ai.google.genai.GoogleGenAiChatOptions; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; +import org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +48,7 @@ public class FunctionCallWithPromptFunctionIT { void functionCallTestWithApiKey() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.api-key=" + System.getenv("GOOGLE_API_KEY")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner .withPropertyValues("spring.ai.google.genai.chat.options.model=" @@ -92,7 +93,7 @@ void functionCallTestWithVertexAi() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.project-id=" + System.getenv("GOOGLE_CLOUD_PROJECT"), "spring.ai.google.genai.location=" + System.getenv("GOOGLE_CLOUD_LOCATION")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiChatAutoConfiguration.class)); contextRunner .withPropertyValues("spring.ai.google.genai.chat.options.model=" diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfigurationIT.java index 1c4ce1f5c62..93db12b0f07 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfigurationIT.java @@ -23,7 +23,7 @@ import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.google.genai.text.GoogleGenAiTextEmbeddingModel; -import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -43,7 +43,7 @@ public class GoogleGenAiTextEmbeddingAutoConfigurationIT { void embeddingWithApiKey() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.embedding.api-key=" + System.getenv("GOOGLE_API_KEY")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiEmbeddingAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiTextEmbeddingAutoConfiguration.class)); contextRunner.run(context -> { GoogleGenAiTextEmbeddingModel embeddingModel = context.getBean(GoogleGenAiTextEmbeddingModel.class); @@ -64,7 +64,7 @@ void embeddingWithVertexAi() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.google.genai.embedding.project-id=" + System.getenv("GOOGLE_CLOUD_PROJECT"), "spring.ai.google.genai.embedding.location=" + System.getenv("GOOGLE_CLOUD_LOCATION")) - .withConfiguration(BaseGoogleGenAiIT.googleGenAiEmbeddingAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiTextEmbeddingAutoConfiguration.class)); contextRunner.run(context -> { GoogleGenAiTextEmbeddingModel embeddingModel = context.getBean(GoogleGenAiTextEmbeddingModel.class); @@ -95,7 +95,8 @@ void embeddingModelActivation() { }); // Test that embedding model is activated when enabled - contextRunner.withConfiguration(BaseGoogleGenAiIT.googleGenAiEmbeddingAutoConfig()) + contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(GoogleGenAiTextEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding.text=google-genai") .run(context -> { assertThat(context.getBeansOfType(GoogleGenAiTextEmbeddingProperties.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java index dcf772a0bf7..f14a5a11b1c 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java @@ -32,11 +32,8 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxChatOptions; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -52,9 +49,7 @@ public class FunctionCallbackInPromptIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.apiKey=" + System.getenv("MINIMAX_API_KEY")) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java index 0cb23c746a9..e51a7294fea 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java @@ -34,10 +34,7 @@ import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxChatOptions; import org.springframework.ai.model.tool.ToolCallingChatOptions; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -56,9 +53,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.apiKey=" + System.getenv("MINIMAX_API_KEY")) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .withUserConfiguration(Config.class); // FIXME: multiple function calls may stop prematurely due to model performance diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java index 543ad444578..286b68e10c1 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java @@ -31,10 +31,7 @@ import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxEmbeddingModel; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -53,9 +50,7 @@ public class MiniMaxAutoConfigurationIT { @Test void generate() { - this.contextRunner.withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { MiniMaxChatModel chatModel = context.getBean(MiniMaxChatModel.class); String response = chatModel.call("Hello"); @@ -66,9 +61,7 @@ void generate() { @Test void generateStreaming() { - this.contextRunner.withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { MiniMaxChatModel chatModel = context.getBean(MiniMaxChatModel.class); Flux responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello"))); @@ -85,10 +78,7 @@ void generateStreaming() { @Test void embedding() { - this.contextRunner - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { MiniMaxEmbeddingModel embeddingModel = context.getBean(MiniMaxEmbeddingModel.class); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java index 8e41a0641dd..ed339abbb92 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java @@ -32,11 +32,8 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxChatOptions; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -45,6 +42,7 @@ /** * @author Geng Rong + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "MINIMAX_API_KEY", matches = ".*") public class MiniMaxFunctionCallbackIT { @@ -53,9 +51,7 @@ public class MiniMaxFunctionCallbackIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.apiKey=" + System.getenv("MINIMAX_API_KEY")) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - MiniMaxChatAutoConfiguration.class, ToolCallingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java index c0751d5e334..d5b20f4b365 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java @@ -24,10 +24,7 @@ import org.springframework.ai.minimax.MiniMaxEmbeddingModel; import org.springframework.ai.minimax.api.MiniMaxApi; import org.springframework.ai.model.ModelOptionsUtils; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -51,9 +48,7 @@ public void chatProperties() { "spring.ai.minimax.chat.options.model=MODEL_XYZ", "spring.ai.minimax.chat.options.temperature=0.55") // @formatter:on - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(MiniMaxChatProperties.class); var connectionProperties = context.getBean(MiniMaxConnectionProperties.class); @@ -81,9 +76,7 @@ public void chatOverrideConnectionProperties() { "spring.ai.minimax.chat.options.model=MODEL_XYZ", "spring.ai.minimax.chat.options.temperature=0.55") // @formatter:on - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(MiniMaxChatProperties.class); var connectionProperties = context.getBean(MiniMaxConnectionProperties.class); @@ -108,8 +101,7 @@ public void embeddingProperties() { "spring.ai.minimax.api-key=abc123", "spring.ai.minimax.embedding.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(MiniMaxEmbeddingProperties.class); var connectionProperties = context.getBean(MiniMaxConnectionProperties.class); @@ -135,8 +127,7 @@ public void embeddingOverrideConnectionProperties() { "spring.ai.minimax.embedding.api-key=456", "spring.ai.minimax.embedding.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(MiniMaxEmbeddingProperties.class); var connectionProperties = context.getBean(MiniMaxConnectionProperties.class); @@ -202,9 +193,7 @@ public void chatOptionsTest() { """ ) // @formatter:on - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(MiniMaxChatProperties.class); var connectionProperties = context.getBean(MiniMaxConnectionProperties.class); @@ -249,8 +238,7 @@ public void embeddingOptionsTest() { "spring.ai.minimax.embedding.options.encodingFormat=MyEncodingFormat" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(MiniMaxConnectionProperties.class); var embeddingProperties = context.getBean(MiniMaxEmbeddingProperties.class); @@ -268,8 +256,7 @@ void embeddingActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL", "spring.ai.model.embedding=none") - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(MiniMaxEmbeddingProperties.class)).isEmpty(); assertThat(context.getBeansOfType(MiniMaxEmbeddingModel.class)).isEmpty(); @@ -277,8 +264,7 @@ void embeddingActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(MiniMaxEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MiniMaxEmbeddingModel.class)).isNotEmpty(); @@ -287,8 +273,7 @@ void embeddingActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL", "spring.ai.model.embedding=minimax") - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(MiniMaxEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MiniMaxEmbeddingModel.class)).isNotEmpty(); @@ -300,9 +285,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL", "spring.ai.model.chat=none") - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(MiniMaxChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(MiniMaxChatModel.class)).isEmpty(); @@ -310,9 +293,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL") - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(MiniMaxChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MiniMaxChatModel.class)).isNotEmpty(); @@ -321,9 +302,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL", "spring.ai.model.chat=minimax") - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(MiniMaxChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MiniMaxChatModel.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java index cf1b622d1ff..5339c259532 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java @@ -20,10 +20,7 @@ import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxEmbeddingModel; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -37,14 +34,11 @@ public class MinimaxModelConfigurationTests { private final ApplicationContextRunner chatContextRunner = new ApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, MiniMaxChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxChatAutoConfiguration.class)) .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL"); private final ApplicationContextRunner embeddingContextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MiniMaxEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(MiniMaxEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.minimax.api-key=API_KEY", "spring.ai.minimax.base-url=TEST_BASE_URL"); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/BaseMistralAiIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/BaseMistralAiIT.java deleted file mode 100644 index 1ca25e49229..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/BaseMistralAiIT.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.mistralai.autoconfigure; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; - -/** - * Base class to provide consistent AutoConfigurations for MistralAI integration tests. - */ -public abstract class BaseMistralAiIT { - - /** - * AutoConfigurations needed for MistralAI Chat model. - */ - public static AutoConfigurations mistralAiChatAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class, - MistralAiChatAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - - /** - * AutoConfigurations needed for MistralAI Text Embedding model. - */ - public static AutoConfigurations mistralAiEmbeddingAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, MistralAiEmbeddingAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - - /** - * AutoConfigurations needed for MistralAI OCR API. - */ - public static AutoConfigurations mistralAiOCRAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, MistralAiOcrAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - - /** - * AutoConfigurations needed for MistralAI Moderation API. - */ - public static AutoConfigurations mistralAiModerationAutoConfig(Class... additional) { - Class[] dependencies = { SpringAiRetryAutoConfiguration.class, MistralAiModerationAutoConfiguration.class }; - Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); - return AutoConfigurations.of(all); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiAutoConfigurationIT.java index cde1d627799..96f6ad3650f 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiAutoConfigurationIT.java @@ -31,6 +31,7 @@ import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.mistralai.MistralAiChatModel; import org.springframework.ai.mistralai.MistralAiEmbeddingModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -38,6 +39,7 @@ /** * @author Christian Tzolov * @author Ilayaperumal Gopinathan + * @author Issam El-atif * @since 0.8.1 */ @EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".*") @@ -50,45 +52,49 @@ public class MistralAiAutoConfigurationIT { @Test void generate() { - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()).run(context -> { - MistralAiChatModel chatModel = context.getBean(MistralAiChatModel.class); - String response = chatModel.call("Hello"); - assertThat(response).isNotEmpty(); - logger.info("Response: " + response); - }); + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)) + .run(context -> { + MistralAiChatModel chatModel = context.getBean(MistralAiChatModel.class); + String response = chatModel.call("Hello"); + assertThat(response).isNotEmpty(); + logger.info("Response: " + response); + }); } @Test void generateStreaming() { - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()).run(context -> { - MistralAiChatModel chatModel = context.getBean(MistralAiChatModel.class); - Flux responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello"))); - String response = responseFlux.collectList() - .block() - .stream() - .map(chatResponse -> chatResponse.getResults().get(0).getOutput().getText()) - .collect(Collectors.joining()); + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)) + .run(context -> { + MistralAiChatModel chatModel = context.getBean(MistralAiChatModel.class); + Flux responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello"))); + String response = responseFlux.collectList() + .block() + .stream() + .map(chatResponse -> chatResponse.getResults().get(0).getOutput().getText()) + .collect(Collectors.joining()); - assertThat(response).isNotEmpty(); - logger.info("Response: " + response); - }); + assertThat(response).isNotEmpty(); + logger.info("Response: " + response); + }); } @Test void embedding() { - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()).run(context -> { - MistralAiEmbeddingModel embeddingModel = context.getBean(MistralAiEmbeddingModel.class); + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiEmbeddingAutoConfiguration.class)) + .run(context -> { + MistralAiEmbeddingModel embeddingModel = context.getBean(MistralAiEmbeddingModel.class); - EmbeddingResponse embeddingResponse = embeddingModel - .embedForResponse(List.of("Hello World", "World is big and salvation is near")); - assertThat(embeddingResponse.getResults()).hasSize(2); - assertThat(embeddingResponse.getResults().get(0).getOutput()).isNotEmpty(); - assertThat(embeddingResponse.getResults().get(0).getIndex()).isEqualTo(0); - assertThat(embeddingResponse.getResults().get(1).getOutput()).isNotEmpty(); - assertThat(embeddingResponse.getResults().get(1).getIndex()).isEqualTo(1); + EmbeddingResponse embeddingResponse = embeddingModel + .embedForResponse(List.of("Hello World", "World is big and salvation is near")); + assertThat(embeddingResponse.getResults()).hasSize(2); + assertThat(embeddingResponse.getResults().get(0).getOutput()).isNotEmpty(); + assertThat(embeddingResponse.getResults().get(0).getIndex()).isEqualTo(0); + assertThat(embeddingResponse.getResults().get(1).getOutput()).isNotEmpty(); + assertThat(embeddingResponse.getResults().get(1).getIndex()).isEqualTo(1); - assertThat(embeddingModel.dimensions()).isEqualTo(1024); - }); + assertThat(embeddingModel.dimensions()).isEqualTo(1024); + }); } } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfigurationTests.java index 9aaabb03018..89f328fabac 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfigurationTests.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.mistralai.ocr.MistralOcrApi; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.http.ResponseEntity; @@ -37,6 +38,7 @@ *

* * @author Alexandros Pappas + * @author Issam El-atif * @since 1.1.0 */ @EnabledIfEnvironmentVariable(named = MistralAiOcrAutoConfigurationTests.ENV_VAR_NAME, matches = ".*") @@ -46,7 +48,7 @@ class MistralAiOcrAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.mistralai.api-key=" + System.getenv(ENV_VAR_NAME)) - .withConfiguration(BaseMistralAiIT.mistralAiOCRAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiOcrAutoConfiguration.class)); @Test void ocrExtractionWithPublicUrl() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java index 3b494c7f713..fd47b5be995 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java @@ -19,9 +19,8 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.mistralai.ocr.MistralOcrApi; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -31,13 +30,14 @@ * {@link MistralAiCommonProperties}. * * @author Alexandros Pappas + * @author Issam El-atif * @since 1.1.0 */ class MistralAiOcrPropertiesTests { // Define common configurations to load in tests - private final AutoConfigurations autoConfigurations = AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, MistralAiOcrAutoConfiguration.class); + private final AutoConfigurations autoConfigurations = SpringAiTestAutoConfigurations + .of(MistralAiOcrAutoConfiguration.class); @Test void commonPropertiesAppliedToOcr() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiPropertiesTests.java index c4d68e1b1d4..f720c818ff7 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiPropertiesTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.mistralai.api.MistralAiApi; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -34,7 +35,7 @@ public void embeddingProperties() { new ApplicationContextRunner() .withPropertyValues("spring.ai.mistralai.base-url=TEST_BASE_URL", "spring.ai.mistralai.api-key=abc123", "spring.ai.mistralai.embedding.options.model=MODEL_XYZ") - .withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(MistralAiEmbeddingProperties.class); var connectionProperties = context.getBean(MistralAiCommonProperties.class); @@ -82,7 +83,7 @@ public void chatOptionsTest() { "spring.ai.mistralai.api-key=abc123", "spring.ai.mistralai.embedding.base-url=TEST_BASE_URL2", "spring.ai.mistralai.embedding.api-key=456", "spring.ai.mistralai.embedding.options.model=MODEL_XYZ") - .withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(MistralAiChatProperties.class); @@ -102,7 +103,7 @@ public void embeddingOverrideConnectionProperties() { new ApplicationContextRunner().withPropertyValues("spring.ai.mistralai.base-url=TEST_BASE_URL", "spring.ai.mistralai.api-key=abc123", "spring.ai.mistralai.embedding.base-url=TEST_BASE_URL2", "spring.ai.mistralai.embedding.api-key=456", "spring.ai.mistralai.embedding.options.model=MODEL_XYZ") - .withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(MistralAiEmbeddingProperties.class); var connectionProperties = context.getBean(MistralAiCommonProperties.class); @@ -124,7 +125,7 @@ public void embeddingOptionsTest() { .withPropertyValues("spring.ai.mistralai.api-key=API_KEY", "spring.ai.mistralai.base-url=TEST_BASE_URL", "spring.ai.mistralai.embedding.options.model=MODEL_XYZ", "spring.ai.mistralai.embedding.options.encodingFormat=MyEncodingFormat") - .withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(MistralAiCommonProperties.class); var embeddingProperties = context.getBean(MistralAiEmbeddingProperties.class); @@ -143,7 +144,7 @@ public void moderationOptionsTest() { .withPropertyValues("spring.ai.mistralai.moderation.base-url=TEST_BASE_URL", "spring.ai.mistralai.moderation.api-key=abc123", "spring.ai.mistralai.moderation.options.model=MODERATION_MODEL") - .withConfiguration(BaseMistralAiIT.mistralAiModerationAutoConfig()) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiModerationAutoConfiguration.class)) .run(context -> { var moderationProperties = context.getBean(MistralAiModerationProperties.class); assertThat(moderationProperties.getBaseUrl()).isEqualTo("TEST_BASE_URL"); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java index a16f5b21191..4e9e4dc6de3 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralModelConfigurationTests.java @@ -21,6 +21,7 @@ import org.springframework.ai.mistralai.MistralAiChatModel; import org.springframework.ai.mistralai.MistralAiEmbeddingModel; import org.springframework.ai.mistralai.moderation.MistralAiModerationModel; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -30,15 +31,25 @@ * * @author Ilayaperumal Gopinathan * @author Ricken Bazolo + * @author Issam El-atif */ public class MistralModelConfigurationTests { - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")); + private final ApplicationContextRunner chatContextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)); + + private final ApplicationContextRunner embeddingContextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiEmbeddingAutoConfiguration.class)); + + private final ApplicationContextRunner moderationContextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiModerationAutoConfiguration.class)); @Test void chatModelActivation() { - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()).run(context -> { + this.chatContextRunner.run(context -> { assertThat(context.getBeansOfType(MistralAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MistralAiChatModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(MistralAiEmbeddingProperties.class)).isEmpty(); @@ -47,15 +58,13 @@ void chatModelActivation() { assertThat(context.getBeansOfType(MistralAiModerationModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()) - .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none") + this.chatContextRunner.withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none") .run(context -> { assertThat(context.getBeansOfType(MistralAiChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(MistralAiChatModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()) - .withPropertyValues("spring.ai.model.chat=mistral", "spring.ai.model.embedding=none") + this.chatContextRunner.withPropertyValues("spring.ai.model.chat=mistral", "spring.ai.model.embedding=none") .run(context -> { assertThat(context.getBeansOfType(MistralAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MistralAiChatModel.class)).isNotEmpty(); @@ -68,27 +77,23 @@ void chatModelActivation() { @Test void embeddingModelActivation() { - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()) + this.embeddingContextRunner .run(context -> assertThat(context.getBeansOfType(MistralAiEmbeddingModel.class)).isNotEmpty()); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()) - .withPropertyValues("spring.ai.model.embedding=none") - .run(context -> { - assertThat(context.getBeansOfType(MistralAiEmbeddingProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(MistralAiEmbeddingModel.class)).isEmpty(); - }); + this.embeddingContextRunner.withPropertyValues("spring.ai.model.embedding=none").run(context -> { + assertThat(context.getBeansOfType(MistralAiEmbeddingProperties.class)).isEmpty(); + assertThat(context.getBeansOfType(MistralAiEmbeddingModel.class)).isEmpty(); + }); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiEmbeddingAutoConfig()) - .withPropertyValues("spring.ai.model.embedding=mistral") - .run(context -> { - assertThat(context.getBeansOfType(MistralAiEmbeddingProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(MistralAiEmbeddingModel.class)).isNotEmpty(); - }); + this.embeddingContextRunner.withPropertyValues("spring.ai.model.embedding=mistral").run(context -> { + assertThat(context.getBeansOfType(MistralAiEmbeddingProperties.class)).isNotEmpty(); + assertThat(context.getBeansOfType(MistralAiEmbeddingModel.class)).isNotEmpty(); + }); } @Test void moderationModelActivation() { - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiModerationAutoConfig()).run(context -> { + this.moderationContextRunner.run(context -> { assertThat(context.getBeansOfType(MistralAiModerationModel.class)).isNotEmpty(); assertThat(context.getBeansOfType(MistralAiModerationProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(MistralAiChatModel.class)).isEmpty(); @@ -97,21 +102,17 @@ void moderationModelActivation() { assertThat(context.getBeansOfType(MistralAiEmbeddingModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiModerationAutoConfig()) - .withPropertyValues("spring.ai.model.moderation=none") - .run(context -> { - assertThat(context.getBeansOfType(MistralAiModerationProperties.class)).isEmpty(); - assertThat(context.getBeansOfType(MistralAiModerationModel.class)).isEmpty(); - }); + this.moderationContextRunner.withPropertyValues("spring.ai.model.moderation=none").run(context -> { + assertThat(context.getBeansOfType(MistralAiModerationProperties.class)).isEmpty(); + assertThat(context.getBeansOfType(MistralAiModerationModel.class)).isEmpty(); + }); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiModerationAutoConfig()) - .withPropertyValues("spring.ai.model.moderation=mistral") - .run(context -> { - assertThat(context.getBeansOfType(MistralAiModerationProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(MistralAiModerationModel.class)).isNotEmpty(); - }); + this.moderationContextRunner.withPropertyValues("spring.ai.model.moderation=mistral").run(context -> { + assertThat(context.getBeansOfType(MistralAiModerationProperties.class)).isNotEmpty(); + assertThat(context.getBeansOfType(MistralAiModerationModel.class)).isNotEmpty(); + }); - this.contextRunner.withConfiguration(BaseMistralAiIT.mistralAiModerationAutoConfig()) + this.moderationContextRunner .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.moderation=mistral") .run(context -> { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanIT.java index e0766e64111..69f0e153a8e 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanIT.java @@ -32,7 +32,8 @@ import org.springframework.ai.mistralai.MistralAiChatModel; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; -import org.springframework.ai.model.mistralai.autoconfigure.BaseMistralAiIT; +import org.springframework.ai.model.mistralai.autoconfigure.MistralAiChatAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -52,7 +53,7 @@ class PaymentStatusBeanIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) - .withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()) + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanOpenAiIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanOpenAiIT.java index 7b48dde3367..1ebb98af66a 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanOpenAiIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusBeanOpenAiIT.java @@ -31,11 +31,9 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiChatOptions; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -48,6 +46,7 @@ * AI Function Calling implementation. * * @author Christian Tzolov + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".*") class PaymentStatusBeanOpenAiIT { @@ -62,8 +61,7 @@ class PaymentStatusBeanOpenAiIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY"), "spring.ai.openai.chat.base-url=https://api.mistral.ai") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class, - SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusPromptIT.java index 68bcd89e083..065f7a20468 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusPromptIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/PaymentStatusPromptIT.java @@ -31,8 +31,9 @@ import org.springframework.ai.mistralai.MistralAiChatModel; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; -import org.springframework.ai.model.mistralai.autoconfigure.BaseMistralAiIT; +import org.springframework.ai.model.mistralai.autoconfigure.MistralAiChatAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +51,7 @@ public class PaymentStatusPromptIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.mistralai.apiKey=" + System.getenv("MISTRAL_AI_API_KEY")) - .withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/WeatherServicePromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/WeatherServicePromptIT.java index f923bf2268a..ad1f052f714 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/WeatherServicePromptIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/tool/WeatherServicePromptIT.java @@ -34,11 +34,12 @@ import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionRequest.ToolChoice; -import org.springframework.ai.model.mistralai.autoconfigure.BaseMistralAiIT; +import org.springframework.ai.model.mistralai.autoconfigure.MistralAiChatAutoConfiguration; import org.springframework.ai.model.mistralai.autoconfigure.tool.WeatherServicePromptIT.MyWeatherService.Request; import org.springframework.ai.model.mistralai.autoconfigure.tool.WeatherServicePromptIT.MyWeatherService.Response; import org.springframework.ai.model.tool.ToolCallingChatOptions; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -46,6 +47,7 @@ /** * @author Christian Tzolov * @author Alexandros Pappas + * @author Issam El-atif * @since 0.8.1 */ @EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".*") @@ -55,7 +57,7 @@ public class WeatherServicePromptIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.mistralai.api-key=" + System.getenv("MISTRAL_AI_API_KEY")) - .withConfiguration(BaseMistralAiIT.mistralAiChatAutoConfig()); + .withConfiguration(SpringAiTestAutoConfigurations.of(MistralAiChatAutoConfiguration.class)); @Test void promptFunctionCall() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAIAutoConfigurationTest.java b/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAIAutoConfigurationTest.java index 55f316ffdd7..4bca60c5590 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAIAutoConfigurationTest.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAIAutoConfigurationTest.java @@ -27,7 +27,7 @@ import org.springframework.ai.oci.cohere.OCICohereChatModel; import org.springframework.ai.oci.cohere.OCICohereChatOptions; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -56,9 +56,7 @@ void setProperties(@TempDir Path tempDir) throws Exception { "spring.ai.oci.genai.cohere.chat.options.frequencyPenalty=0.1", "spring.ai.oci.genai.cohere.chat.options.presencePenalty=0.2" // @formatter:on - ) - .withConfiguration(AutoConfigurations.of(OCIGenAiInferenceClientAutoConfiguration.class, - OCIGenAiChatAutoConfiguration.class)); + ).withConfiguration(SpringAiTestAutoConfigurations.of(OCIGenAiChatAutoConfiguration.class)); contextRunner.run(context -> { OCICohereChatModel chatModel = context.getBean(OCICohereChatModel.class); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAiAutoConfigurationIT.java index 5aefa998e53..c7a33a6444e 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAiAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-oci-genai/src/test/java/org/springframework/ai/model/oci/genai/autoconfigure/OCIGenAiAutoConfigurationIT.java @@ -26,7 +26,7 @@ import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.oci.OCIEmbeddingModel; import org.springframework.ai.oci.cohere.OCICohereChatModel; -import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -52,9 +52,7 @@ public class OCIGenAiAutoConfigurationIT { "spring.ai.oci.genai.embedding.servingMode=on-demand", "spring.ai.oci.genai.embedding.model=cohere.embed-english-light-v2.0" // @formatter:on - ) - .withConfiguration(AutoConfigurations.of(OCIGenAiInferenceClientAutoConfiguration.class, - OCIGenAiEmbeddingAutoConfiguration.class)); + ).withConfiguration(SpringAiTestAutoConfigurations.of(OCIGenAiEmbeddingAutoConfiguration.class)); private final ApplicationContextRunner cohereChatContextRunner = new ApplicationContextRunner().withPropertyValues( // @formatter:off @@ -64,9 +62,7 @@ public class OCIGenAiAutoConfigurationIT { "spring.ai.oci.genai.cohere.chat.options.servingMode=on-demand", "spring.ai.oci.genai.cohere.chat.options.model=" + this.CHAT_MODEL_ID // @formatter:on - ) - .withConfiguration(AutoConfigurations.of(OCIGenAiInferenceClientAutoConfiguration.class, - OCIGenAiChatAutoConfiguration.class)); + ).withConfiguration(SpringAiTestAutoConfigurations.of(OCIGenAiChatAutoConfiguration.class)); @Test void embeddings() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java index 9a3bc2527f4..bac09ffadff 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java @@ -17,20 +17,21 @@ package org.springframework.ai.model.ollama.autoconfigure; import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.ollama.OllamaContainer; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.ollama.api.OllamaApi; import org.springframework.ai.ollama.management.ModelManagementOptions; import org.springframework.ai.ollama.management.OllamaModelManager; import org.springframework.ai.ollama.management.PullModelStrategy; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.util.Assert; @Testcontainers @@ -103,8 +104,7 @@ public static OllamaApi buildOllamaApiWithModel(final String model) { } public String getBaseUrl() { - String baseUrl = SKIP_CONTAINER_CREATION ? OLLAMA_LOCAL_URL : ollamaContainer.getEndpoint(); - return baseUrl; + return SKIP_CONTAINER_CREATION ? OLLAMA_LOCAL_URL : ollamaContainer.getEndpoint(); } private static void ensureModelIsPresent(final OllamaApi ollamaApi, final String model) { @@ -117,14 +117,9 @@ private static void ensureModelIsPresent(final OllamaApi ollamaApi, final String } public static AutoConfigurations ollamaAutoConfig(Class... additionalAutoConfigurations) { - Class[] dependencies = new Class[] { OllamaApiAutoConfiguration.class, RestClientAutoConfiguration.class, - SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class }; - Class[] allAutoConfigurations = new Class[dependencies.length + additionalAutoConfigurations.length]; - System.arraycopy(dependencies, 0, allAutoConfigurations, 0, dependencies.length); - System.arraycopy(additionalAutoConfigurations, 0, allAutoConfigurations, dependencies.length, - additionalAutoConfigurations.length); - - return AutoConfigurations.of(allAutoConfigurations); + List> autoConfigurations = new ArrayList<>(Arrays.asList(additionalAutoConfigurations)); + autoConfigurations.add(OllamaApiAutoConfiguration.class); + return SpringAiTestAutoConfigurations.of(autoConfigurations.toArray(new Class[0])); } } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java index 46dec5cb44c..1ed687ff370 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java @@ -26,10 +26,7 @@ import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.ChatClientCustomizer; import org.springframework.ai.model.chat.client.autoconfigure.ChatClientAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -48,9 +45,8 @@ public class ChatClientAutoConfigurationIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"), "spring.ai.openai.chat.options.model=gpt-4o") - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, ToolCallingAutoConfiguration.class, - OpenAiChatAutoConfiguration.class, ChatClientAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + ChatClientAutoConfiguration.class)); @Test void implicitlyEnabled() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java index 78e920f7f08..8cbacee1ac6 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java @@ -33,17 +33,13 @@ import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiAudioSpeechModel; import org.springframework.ai.openai.OpenAiAudioTranscriptionModel; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -56,19 +52,17 @@ public class OpenAiAutoConfigurationIT { private static final Log logger = LogFactory.getLog(OpenAiAutoConfigurationIT.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY")) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - WebClientAutoConfiguration.class, ToolCallingAutoConfiguration.class)); + .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY")); @Test void chatCall() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)).run(context -> { - OpenAiChatModel chatModel = context.getBean(OpenAiChatModel.class); - String response = chatModel.call("Hello"); - assertThat(response).isNotEmpty(); - logger.info("Response: " + response); - }); + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .run(context -> { + OpenAiChatModel chatModel = context.getBean(OpenAiChatModel.class); + String response = chatModel.call("Hello"); + assertThat(response).isNotEmpty(); + logger.info("Response: " + response); + }); } @Test @@ -79,7 +73,7 @@ void chatCallAudioResponse() { "spring.ai.openai.chat.options.output-modalities=text,audio", "spring.ai.openai.chat.options.output-audio.voice=ALLOY", "spring.ai.openai.chat.options.output-audio.format=WAV") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { OpenAiChatModel chatModel = context.getBean(OpenAiChatModel.class); @@ -93,7 +87,8 @@ void chatCallAudioResponse() { @Test void transcribe() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { OpenAiAudioTranscriptionModel transcriptionModel = context.getBean(OpenAiAudioTranscriptionModel.class); Resource audioFile = new ClassPathResource("/speech/jfk.flac"); @@ -105,7 +100,8 @@ void transcribe() { @Test void speech() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { OpenAiAudioSpeechModel speechModel = context.getBean(OpenAiAudioSpeechModel.class); byte[] response = speechModel.call("H"); @@ -132,24 +128,25 @@ public boolean verifyMp3FrameHeader(byte[] audioResponse) { @Test void generateStreaming() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)).run(context -> { - OpenAiChatModel chatModel = context.getBean(OpenAiChatModel.class); - Flux responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello"))); - String response = responseFlux.collectList() - .block() - .stream() - .map(chatResponse -> chatResponse.getResults().get(0).getOutput().getText()) - .collect(Collectors.joining()); - - assertThat(response).isNotEmpty(); - logger.info("Response: " + response); - }); + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .run(context -> { + OpenAiChatModel chatModel = context.getBean(OpenAiChatModel.class); + Flux responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello"))); + String response = responseFlux.collectList() + .block() + .stream() + .map(chatResponse -> chatResponse.getResults().get(0).getOutput().getText()) + .collect(Collectors.joining()); + + assertThat(response).isNotEmpty(); + logger.info("Response: " + response); + }); } @Test void streamingWithTokenUsage() { this.contextRunner.withPropertyValues("spring.ai.openai.chat.options.stream-usage=true") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { OpenAiChatModel chatModel = context.getBean(OpenAiChatModel.class); @@ -172,7 +169,7 @@ void streamingWithTokenUsage() { @Test void embedding() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { OpenAiEmbeddingModel embeddingModel = context.getBean(OpenAiEmbeddingModel.class); @@ -191,7 +188,7 @@ void embedding() { @Test void generateImage() { this.contextRunner.withPropertyValues("spring.ai.openai.image.options.size=1024x1024") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class); ImageResponse imageResponse = imageModel.call(new ImagePrompt("forest")); @@ -207,7 +204,7 @@ void generateImageWithModel() { this.contextRunner .withPropertyValues("spring.ai.openai.image.options.model=dall-e-2", "spring.ai.openai.image.options.size=256x256") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class); ImageResponse imageResponse = imageModel.call(new ImagePrompt("forest")); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java index b5797172932..2d720dec24a 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java @@ -18,7 +18,6 @@ import org.junit.jupiter.api.Test; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiAudioSpeechModel; import org.springframework.ai.openai.OpenAiAudioTranscriptionModel; import org.springframework.ai.openai.OpenAiChatModel; @@ -26,10 +25,8 @@ import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.OpenAiModerationModel; import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -43,31 +40,29 @@ public class OpenAiModelConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - WebClientAutoConfiguration.class, ToolCallingAutoConfiguration.class)); + .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL"); @Test void chatModelActivation() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)).run(context -> { - assertThat(context.getBeansOfType(OpenAiApi.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); - }); - - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OpenAiApi.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); + }); + + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none") .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=openai") .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); @@ -75,10 +70,10 @@ void chatModelActivation() { }); this.contextRunner - .withConfiguration( - AutoConfigurations.of(OpenAiChatAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class, - OpenAiImageAutoConfiguration.class, OpenAiAudioSpeechAutoConfiguration.class, - OpenAiAudioTranscriptionAutoConfiguration.class, OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + OpenAiEmbeddingAutoConfiguration.class, OpenAiImageAutoConfiguration.class, + OpenAiAudioSpeechAutoConfiguration.class, OpenAiAudioTranscriptionAutoConfiguration.class, + OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=openai", "spring.ai.model.embedding=none", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -94,7 +89,7 @@ void chatModelActivation() { @Test void embeddingModelActivation() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isNotEmpty(); @@ -105,24 +100,24 @@ void embeddingModelActivation() { }); this.contextRunner.withPropertyValues("spring.ai.model.embedding=none") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); }); this.contextRunner.withPropertyValues("spring.ai.model.embedding=openai") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isNotEmpty(); }); this.contextRunner - .withConfiguration( - AutoConfigurations.of(OpenAiChatAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class, - OpenAiImageAutoConfiguration.class, OpenAiAudioSpeechAutoConfiguration.class, - OpenAiAudioTranscriptionAutoConfiguration.class, OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + OpenAiEmbeddingAutoConfiguration.class, OpenAiImageAutoConfiguration.class, + OpenAiAudioSpeechAutoConfiguration.class, OpenAiAudioTranscriptionAutoConfiguration.class, + OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=openai", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -139,23 +134,24 @@ void embeddingModelActivation() { @Test void imageModelActivation() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)).run(context -> { - assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty(); - assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); - assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); - }); - - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); + assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); + }); + + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .withPropertyValues("spring.ai.model.image=none") .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .withPropertyValues("spring.ai.model.image=openai") .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty(); @@ -163,10 +159,10 @@ void imageModelActivation() { }); this.contextRunner - .withConfiguration( - AutoConfigurations.of(OpenAiChatAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class, - OpenAiImageAutoConfiguration.class, OpenAiAudioSpeechAutoConfiguration.class, - OpenAiAudioTranscriptionAutoConfiguration.class, OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + OpenAiEmbeddingAutoConfiguration.class, OpenAiImageAutoConfiguration.class, + OpenAiAudioSpeechAutoConfiguration.class, OpenAiAudioTranscriptionAutoConfiguration.class, + OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.image=openai", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -183,7 +179,8 @@ void imageModelActivation() { @Test void audioSpeechModelActivation() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); @@ -193,14 +190,16 @@ void audioSpeechModelActivation() { assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.speech=none") .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.speech=openai") .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isNotEmpty(); @@ -208,10 +207,10 @@ void audioSpeechModelActivation() { }); this.contextRunner - .withConfiguration( - AutoConfigurations.of(OpenAiChatAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class, - OpenAiImageAutoConfiguration.class, OpenAiAudioSpeechAutoConfiguration.class, - OpenAiAudioTranscriptionAutoConfiguration.class, OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + OpenAiEmbeddingAutoConfiguration.class, OpenAiImageAutoConfiguration.class, + OpenAiAudioSpeechAutoConfiguration.class, OpenAiAudioTranscriptionAutoConfiguration.class, + OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.image=none", "spring.ai.model.audio.speech=openai", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=none") @@ -227,7 +226,8 @@ void audioSpeechModelActivation() { @Test void audioTranscriptionModelActivation() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); @@ -237,14 +237,16 @@ void audioTranscriptionModelActivation() { assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=none") .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + this.contextRunner + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .withPropertyValues("spring.ai.model.audio.transcription=openai") .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isNotEmpty(); @@ -252,10 +254,10 @@ void audioTranscriptionModelActivation() { }); this.contextRunner - .withConfiguration( - AutoConfigurations.of(OpenAiChatAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class, - OpenAiImageAutoConfiguration.class, OpenAiAudioSpeechAutoConfiguration.class, - OpenAiAudioTranscriptionAutoConfiguration.class, OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + OpenAiEmbeddingAutoConfiguration.class, OpenAiImageAutoConfiguration.class, + OpenAiAudioSpeechAutoConfiguration.class, OpenAiAudioTranscriptionAutoConfiguration.class, + OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=openai", "spring.ai.model.moderation=none") @@ -271,7 +273,7 @@ void audioTranscriptionModelActivation() { @Test void moderationModelActivation() { - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); @@ -281,14 +283,14 @@ void moderationModelActivation() { assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isNotEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.moderation=none") .run(context -> { assertThat(context.getBeansOfType(OpenAiModerationProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiModerationModel.class)).isEmpty(); }); - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.moderation=openai") .run(context -> { assertThat(context.getBeansOfType(OpenAiModerationProperties.class)).isNotEmpty(); @@ -296,10 +298,10 @@ void moderationModelActivation() { }); this.contextRunner - .withConfiguration( - AutoConfigurations.of(OpenAiChatAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class, - OpenAiImageAutoConfiguration.class, OpenAiAudioSpeechAutoConfiguration.class, - OpenAiAudioTranscriptionAutoConfiguration.class, OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class, + OpenAiEmbeddingAutoConfiguration.class, OpenAiImageAutoConfiguration.class, + OpenAiAudioSpeechAutoConfiguration.class, OpenAiAudioTranscriptionAutoConfiguration.class, + OpenAiModerationAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none", "spring.ai.model.embedding=none", "spring.ai.model.image=none", "spring.ai.model.audio.speech=none", "spring.ai.model.audio.transcription=none", "spring.ai.model.moderation=openai") @@ -316,11 +318,12 @@ void moderationModelActivation() { @Test void openAiApiBean() { // Test that OpenAiApi bean is registered and can be injected - this.contextRunner.withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)).run(context -> { - assertThat(context.getBeansOfType(OpenAiApi.class)).hasSize(1); - OpenAiApi openAiApi = context.getBean(OpenAiApi.class); - assertThat(openAiApi).isNotNull(); - }); + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OpenAiApi.class)).hasSize(1); + OpenAiApi openAiApi = context.getBean(OpenAiApi.class); + assertThat(openAiApi).isNotNull(); + }); } } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java index da577eed1ab..4271bbb234b 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java @@ -21,7 +21,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.ai.model.ModelOptionsUtils; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiAudioSpeechModel; import org.springframework.ai.openai.OpenAiAudioTranscriptionModel; import org.springframework.ai.openai.OpenAiChatModel; @@ -30,10 +29,7 @@ import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ToolChoiceBuilder; import org.springframework.ai.openai.api.OpenAiAudioApi; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -51,9 +47,7 @@ */ public class OpenAiPropertiesTests { - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - WebClientAutoConfiguration.class, ToolCallingAutoConfiguration.class)); + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); @Test public void chatProperties() { @@ -65,7 +59,7 @@ public void chatProperties() { "spring.ai.openai.chat.options.model=MODEL_XYZ", "spring.ai.openai.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(OpenAiChatProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -91,7 +85,7 @@ public void transcriptionProperties() { "spring.ai.openai.audio.transcription.options.model=MODEL_XYZ", "spring.ai.openai.audio.transcription.options.temperature=0.55") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { var transcriptionProperties = context.getBean(OpenAiAudioTranscriptionProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -119,7 +113,7 @@ public void chatOverrideConnectionProperties() { "spring.ai.openai.chat.options.model=MODEL_XYZ", "spring.ai.openai.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(OpenAiChatProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -147,7 +141,7 @@ public void transcriptionOverrideConnectionProperties() { "spring.ai.openai.audio.transcription.options.model=MODEL_XYZ", "spring.ai.openai.audio.transcription.options.temperature=0.55") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { var transcriptionProperties = context.getBean(OpenAiAudioTranscriptionProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -175,7 +169,7 @@ public void speechProperties() { "spring.ai.openai.audio.speech.options.response-format=mp3", "spring.ai.openai.audio.speech.options.speed=0.75") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { var speechProperties = context.getBean(OpenAiAudioSpeechProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -206,7 +200,7 @@ public void speechPropertiesTest() { "spring.ai.openai.audio.speech.options.response-format=mp3", "spring.ai.openai.audio.speech.options.speed=0.75") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { var speechProperties = context.getBean(OpenAiAudioSpeechProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -236,7 +230,7 @@ public void speechOverrideConnectionPropertiesTest() { "spring.ai.openai.audio.speech.options.response-format=opus", "spring.ai.openai.audio.speech.options.speed=0.5") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { var speechProperties = context.getBean(OpenAiAudioSpeechProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -265,7 +259,7 @@ public void embeddingProperties() { "spring.ai.openai.api-key=abc123", "spring.ai.openai.embedding.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(OpenAiEmbeddingProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -291,7 +285,7 @@ public void embeddingOverrideConnectionProperties() { "spring.ai.openai.embedding.api-key=456", "spring.ai.openai.embedding.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(OpenAiEmbeddingProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -315,7 +309,7 @@ public void imageProperties() { "spring.ai.openai.image.options.model=MODEL_XYZ", "spring.ai.openai.image.options.n=3") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(OpenAiImageProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -342,7 +336,7 @@ public void imageOverrideConnectionProperties() { "spring.ai.openai.image.options.model=MODEL_XYZ", "spring.ai.openai.image.options.n=3") // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(OpenAiImageProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -409,7 +403,7 @@ public void chatOptionsTest() { "spring.ai.openai.chat.options.user=userXYZ" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(OpenAiChatProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -458,7 +452,7 @@ public void transcriptionOptionsTest() { "spring.ai.openai.audio.transcription.options.temperature=0.55" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { var transcriptionProperties = context.getBean(OpenAiAudioTranscriptionProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -488,7 +482,7 @@ public void embeddingOptionsTest() { "spring.ai.openai.embedding.options.user=userXYZ" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(OpenAiConnectionProperties.class); var embeddingProperties = context.getBean(OpenAiEmbeddingProperties.class); @@ -520,7 +514,7 @@ public void imageOptionsTest() { "spring.ai.openai.image.options.user=userXYZ" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(OpenAiImageProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -546,7 +540,7 @@ void embeddingActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.embedding=none") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); @@ -554,7 +548,7 @@ void embeddingActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isNotEmpty(); @@ -563,7 +557,7 @@ void embeddingActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.embedding=openai") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isNotEmpty(); @@ -575,7 +569,7 @@ void chatActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.chat=none") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); @@ -583,7 +577,7 @@ void chatActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); @@ -592,7 +586,7 @@ void chatActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.chat=openai") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); @@ -605,7 +599,7 @@ void imageActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.image=none") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty(); @@ -613,7 +607,7 @@ void imageActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty(); @@ -622,7 +616,7 @@ void imageActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.image=openai") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty(); @@ -635,7 +629,7 @@ void audioSpeechActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.speech=none") - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); @@ -643,7 +637,7 @@ void audioSpeechActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isNotEmpty(); @@ -652,7 +646,7 @@ void audioSpeechActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.speech=openai") - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isNotEmpty(); @@ -665,7 +659,7 @@ void audioTranscriptionActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.transcription=none") - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); @@ -673,7 +667,7 @@ void audioTranscriptionActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isNotEmpty(); @@ -682,7 +676,7 @@ void audioTranscriptionActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.transcription=openai") - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isNotEmpty(); @@ -696,7 +690,7 @@ public void moderationOptionsTest() { .withPropertyValues("spring.ai.openai.moderation.base-url=TEST_BASE_URL", "spring.ai.openai.moderation.api-key=abc123", "spring.ai.openai.moderation.options.model=MODERATION_MODEL") - .withConfiguration(AutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiModerationAutoConfiguration.class)) .run(context -> { var moderationProperties = context.getBean(OpenAiModerationProperties.class); assertThat(moderationProperties.getBaseUrl()).isEqualTo("TEST_BASE_URL"); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java index 04c2b5813f4..ed6bbb9d317 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java @@ -18,7 +18,6 @@ import org.junit.jupiter.api.Test; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiAudioSpeechModel; import org.springframework.ai.openai.OpenAiAudioTranscriptionModel; import org.springframework.ai.openai.OpenAiChatModel; @@ -26,10 +25,7 @@ import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.api.OpenAiAudioApi; import org.springframework.ai.openai.api.ResponseFormat; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -42,9 +38,7 @@ */ public class OpenAiResponseFormatPropertiesTests { - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - WebClientAutoConfiguration.class, ToolCallingAutoConfiguration.class)); + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); @Test public void responseFormatJsonSchema() { @@ -72,7 +66,7 @@ public void responseFormatJsonSchema() { "spring.ai.openai.chat.options.response-format.strict=true" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(OpenAiChatProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -91,7 +85,7 @@ public void responseFormatJsonObject() { .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.chat.options.response-format.type=JSON_OBJECT") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(OpenAiChatProperties.class); @@ -105,7 +99,7 @@ public void emptyResponseFormat() { this.contextRunner.withPropertyValues("spring.ai.openai.api-key=API_KEY") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(OpenAiChatProperties.class); @@ -128,7 +122,7 @@ public void transcriptionOptionsTest() { "spring.ai.openai.audio.transcription.options.temperature=0.55" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { var transcriptionProperties = context.getBean(OpenAiAudioTranscriptionProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -157,7 +151,7 @@ public void embeddingOptionsTest() { "spring.ai.openai.embedding.options.user=userXYZ" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(OpenAiConnectionProperties.class); var embeddingProperties = context.getBean(OpenAiEmbeddingProperties.class); @@ -189,7 +183,7 @@ public void imageOptionsTest() { "spring.ai.openai.image.options.user=userXYZ" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(OpenAiImageProperties.class); var connectionProperties = context.getBean(OpenAiConnectionProperties.class); @@ -215,7 +209,7 @@ void embeddingActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.embedding=none") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isEmpty(); @@ -223,7 +217,7 @@ void embeddingActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isNotEmpty(); @@ -232,7 +226,7 @@ void embeddingActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.embedding=openai") - .withConfiguration(AutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiEmbeddingModel.class)).isNotEmpty(); @@ -244,7 +238,7 @@ void chatActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.chat=none") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isEmpty(); @@ -252,7 +246,7 @@ void chatActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); @@ -261,7 +255,7 @@ void chatActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.chat=openai") - .withConfiguration(AutoConfigurations.of(OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiChatModel.class)).isNotEmpty(); @@ -274,7 +268,7 @@ void imageActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.image=none") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty(); @@ -282,7 +276,7 @@ void imageActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty(); @@ -291,7 +285,7 @@ void imageActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.image=openai") - .withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiImageProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty(); @@ -304,7 +298,7 @@ void audioSpeechActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.speech=none") - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isEmpty(); @@ -312,7 +306,7 @@ void audioSpeechActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isNotEmpty(); @@ -321,7 +315,7 @@ void audioSpeechActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.speech=openai") - .withConfiguration(AutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioSpeechAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioSpeechProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioSpeechModel.class)).isNotEmpty(); @@ -334,7 +328,7 @@ void audioTranscriptionActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.transcription=none") - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isEmpty(); @@ -342,7 +336,7 @@ void audioTranscriptionActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL") - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isNotEmpty(); @@ -351,7 +345,7 @@ void audioTranscriptionActivation() { this.contextRunner .withPropertyValues("spring.ai.openai.api-key=API_KEY", "spring.ai.openai.base-url=TEST_BASE_URL", "spring.ai.model.audio.transcription=openai") - .withConfiguration(AutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiAudioTranscriptionAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(OpenAiAudioTranscriptionProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(OpenAiAudioTranscriptionModel.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java index d7b90d853ff..0d61adadcdd 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java @@ -27,13 +27,10 @@ import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.api.OpenAiApi.ChatModel; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -45,9 +42,7 @@ public class FunctionCallbackInPrompt2IT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY")) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, OpenAiChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java index 06510dfcdbe..06dfe7f32f3 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java @@ -31,14 +31,11 @@ import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi.ChatModel; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -50,9 +47,7 @@ public class FunctionCallbackInPromptIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY")) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, OpenAiChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java index 75debfb1069..9402c13d122 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java @@ -41,13 +41,10 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; import org.springframework.ai.model.tool.ToolCallingChatOptions; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi.ChatModel; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -63,9 +60,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"), "spring.ai.openai.chat.options.model=" + ChatModel.GPT_4_O_MINI.getName()) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); private static Map feedback = new ConcurrentHashMap<>(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java index a996c4c3e5a..9171e354899 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java @@ -25,14 +25,11 @@ import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.api.OpenAiApi.ChatModel; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -47,9 +44,7 @@ public class OpenAiFunctionCallback2IT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"), "spring.ai.openai.chat.options.model=" + ChatModel.GPT_4_O_MINI.getName()) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java index 9c917b25fdc..84dc6171d1d 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java @@ -31,15 +31,12 @@ import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi.ChatModel; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -54,9 +51,7 @@ public class OpenAiFunctionCallbackIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"), "spring.ai.openai.chat.options.model=" + ChatModel.GPT_4_O_MINI.getName()) - .withConfiguration( - AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, OpenAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(OpenAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/VertexAiITUtil.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/VertexAiITUtil.java deleted file mode 100644 index f9e43220055..00000000000 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/VertexAiITUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2025-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.vertexai.autoconfigure; - -import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration; -import org.springframework.ai.model.vertexai.autoconfigure.embedding.VertexAiEmbeddingConnectionAutoConfiguration; -import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; - -/** - * Utility class for VertexAI integration tests. - * - * @author Pawel Potaczala - */ -public final class VertexAiITUtil { - - private VertexAiITUtil() { - } - - public static AutoConfigurations vertexAiToolAutoConfig(Class... additionalAutoConfigurations) { - Class[] dependencies = new Class[] { SpringAiRetryAutoConfiguration.class, - ToolCallingAutoConfiguration.class }; - Class[] allAutoConfigurations = new Class[dependencies.length + additionalAutoConfigurations.length]; - System.arraycopy(dependencies, 0, allAutoConfigurations, 0, dependencies.length); - System.arraycopy(additionalAutoConfigurations, 0, allAutoConfigurations, dependencies.length, - additionalAutoConfigurations.length); - - return AutoConfigurations.of(allAutoConfigurations); - } - - public static AutoConfigurations vertexAiEmbeddingAutoConfig(Class... additionalAutoConfigurations) { - Class[] dependencies = new Class[] { SpringAiRetryAutoConfiguration.class, - VertexAiEmbeddingConnectionAutoConfiguration.class }; - Class[] allAutoConfigurations = new Class[dependencies.length + additionalAutoConfigurations.length]; - System.arraycopy(dependencies, 0, allAutoConfigurations, 0, dependencies.length); - System.arraycopy(additionalAutoConfigurations, 0, allAutoConfigurations, dependencies.length, - additionalAutoConfigurations.length); - - return AutoConfigurations.of(allAutoConfigurations); - } - -} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingModelAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingModelAutoConfigurationIT.java index ade63bad138..467be5f1b69 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingModelAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingModelAutoConfigurationIT.java @@ -28,7 +28,7 @@ import org.springframework.ai.embedding.EmbeddingOptionsBuilder; import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.embedding.EmbeddingResultMetadata; -import org.springframework.ai.model.vertexai.autoconfigure.VertexAiITUtil; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.vertexai.embedding.multimodal.VertexAiMultimodalEmbeddingModel; import org.springframework.ai.vertexai.embedding.text.VertexAiTextEmbeddingModel; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -38,6 +38,7 @@ /** * @author Christian Tzolov * @author Ilayaperumal Gopinathan + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_PROJECT_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_LOCATION", matches = ".*") @@ -53,7 +54,7 @@ public class VertexAiTextEmbeddingModelAutoConfigurationIT { @Test public void textEmbedding() { this.contextRunner - .withConfiguration(VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiTextEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiTextEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(VertexAiEmbeddingConnectionProperties.class); var textEmbeddingProperties = context.getBean(VertexAiTextEmbeddingProperties.class); @@ -74,7 +75,7 @@ public void textEmbedding() { @Test void textEmbeddingActivation() { this.contextRunner - .withConfiguration(VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiTextEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiTextEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding.text=none") .run(context -> { assertThat(context.getBeansOfType(VertexAiTextEmbeddingProperties.class)).isEmpty(); @@ -82,7 +83,7 @@ void textEmbeddingActivation() { }); this.contextRunner - .withConfiguration(VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiTextEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiTextEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding.text=vertexai") .run(context -> { assertThat(context.getBeansOfType(VertexAiTextEmbeddingProperties.class)).isNotEmpty(); @@ -90,7 +91,7 @@ void textEmbeddingActivation() { }); this.contextRunner - .withConfiguration(VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiTextEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiTextEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(VertexAiTextEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(VertexAiTextEmbeddingModel.class)).isNotEmpty(); @@ -101,8 +102,7 @@ void textEmbeddingActivation() { @Test public void multimodalEmbedding() { this.contextRunner - .withConfiguration( - VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiMultiModalEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiMultiModalEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(VertexAiEmbeddingConnectionProperties.class); var multimodalEmbeddingProperties = context.getBean(VertexAiMultimodalEmbeddingProperties.class); @@ -138,8 +138,7 @@ public void multimodalEmbedding() { @Test void multimodalEmbeddingActivation() { this.contextRunner - .withConfiguration( - VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiMultiModalEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiMultiModalEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding.multimodal=none") .run(context -> { assertThat(context.getBeansOfType(VertexAiMultimodalEmbeddingProperties.class)).isEmpty(); @@ -147,8 +146,7 @@ void multimodalEmbeddingActivation() { }); this.contextRunner - .withConfiguration( - VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiMultiModalEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiMultiModalEmbeddingAutoConfiguration.class)) .withPropertyValues("spring.ai.model.embedding.multimodal=vertexai") .run(context -> { assertThat(context.getBeansOfType(VertexAiMultimodalEmbeddingProperties.class)).isNotEmpty(); @@ -156,8 +154,7 @@ void multimodalEmbeddingActivation() { }); this.contextRunner - .withConfiguration( - VertexAiITUtil.vertexAiEmbeddingAutoConfig(VertexAiMultiModalEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiMultiModalEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(VertexAiMultimodalEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(VertexAiMultimodalEmbeddingModel.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfigurationIT.java index 212c137abaf..fe07b61937c 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfigurationIT.java @@ -27,7 +27,7 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.vertexai.autoconfigure.VertexAiITUtil; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -42,7 +42,7 @@ public class VertexAiGeminiChatAutoConfigurationIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.vertex.ai.gemini.project-id=" + System.getenv("VERTEX_AI_GEMINI_PROJECT_ID"), "spring.ai.vertex.ai.gemini.location=" + System.getenv("VERTEX_AI_GEMINI_LOCATION")) - .withConfiguration(VertexAiITUtil.vertexAiToolAutoConfig(VertexAiGeminiChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiGeminiChatAutoConfiguration.class)); @Test void generate() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiModelConfigurationTests.java index fc3baabb0ef..787bc1ff4d9 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiModelConfigurationTests.java @@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; -import org.springframework.ai.model.vertexai.autoconfigure.VertexAiITUtil; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -29,6 +29,7 @@ * Unit Tests for OpenAI auto configurations' conditional enabling of models. * * @author Ilayaperumal Gopinathan + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_PROJECT_ID", matches = ".*") @EnabledIfEnvironmentVariable(named = "VERTEX_AI_GEMINI_LOCATION", matches = ".*") @@ -42,7 +43,7 @@ public class VertexAiModelConfigurationTests { void chatModelActivation() { this.contextRunner - .withConfiguration(VertexAiITUtil.vertexAiToolAutoConfig(VertexAiGeminiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiGeminiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=none") .run(context -> { assertThat(context.getBeansOfType(VertexAiGeminiChatProperties.class)).isEmpty(); @@ -50,7 +51,7 @@ void chatModelActivation() { }); this.contextRunner - .withConfiguration(VertexAiITUtil.vertexAiToolAutoConfig(VertexAiGeminiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiGeminiChatAutoConfiguration.class)) .withPropertyValues("spring.ai.model.chat=vertexai") .run(context -> { assertThat(context.getBeansOfType(VertexAiGeminiChatProperties.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionBeanIT.java index d598a680c97..eb95bde4c29 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionBeanIT.java @@ -28,8 +28,8 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.tool.ToolCallingChatOptions; -import org.springframework.ai.model.vertexai.autoconfigure.VertexAiITUtil; import org.springframework.ai.model.vertexai.autoconfigure.gemini.VertexAiGeminiChatAutoConfiguration; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -49,7 +49,7 @@ class FunctionCallWithFunctionBeanIT { .withPropertyValues("spring.ai.vertex.ai.gemini.project-id=" + System.getenv("VERTEX_AI_GEMINI_PROJECT_ID"), "spring.ai.vertex.ai.gemini.location=" + System.getenv("VERTEX_AI_GEMINI_LOCATION")) - .withConfiguration(VertexAiITUtil.vertexAiToolAutoConfig(VertexAiGeminiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiGeminiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionWrapperIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionWrapperIT.java index c93b043fc3c..ae1c94047e0 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionWrapperIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithFunctionWrapperIT.java @@ -26,10 +26,10 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.vertexai.autoconfigure.VertexAiITUtil; import org.springframework.ai.model.vertexai.autoconfigure.gemini.VertexAiGeminiChatAutoConfiguration; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -47,7 +47,7 @@ public class FunctionCallWithFunctionWrapperIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.vertex.ai.gemini.project-id=" + System.getenv("VERTEX_AI_GEMINI_PROJECT_ID"), "spring.ai.vertex.ai.gemini.location=" + System.getenv("VERTEX_AI_GEMINI_LOCATION")) - .withConfiguration(VertexAiITUtil.vertexAiToolAutoConfig(VertexAiGeminiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiGeminiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithPromptFunctionIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithPromptFunctionIT.java index 5734ba07b01..b30727c2d8d 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithPromptFunctionIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/test/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/tool/FunctionCallWithPromptFunctionIT.java @@ -26,9 +26,9 @@ import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.vertexai.autoconfigure.VertexAiITUtil; import org.springframework.ai.model.vertexai.autoconfigure.gemini.VertexAiGeminiChatAutoConfiguration; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel; import org.springframework.ai.vertexai.gemini.VertexAiGeminiChatOptions; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -44,7 +44,7 @@ public class FunctionCallWithPromptFunctionIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.vertex.ai.gemini.project-id=" + System.getenv("VERTEX_AI_GEMINI_PROJECT_ID"), "spring.ai.vertex.ai.gemini.location=" + System.getenv("VERTEX_AI_GEMINI_LOCATION")) - .withConfiguration(VertexAiITUtil.vertexAiToolAutoConfig(VertexAiGeminiChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(VertexAiGeminiChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiAutoConfigurationIT.java index ad65b186bc1..ee10dfd6972 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiAutoConfigurationIT.java @@ -32,6 +32,7 @@ import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.zhipuai.ZhiPuAiChatModel; import org.springframework.ai.zhipuai.ZhiPuAiEmbeddingModel; import org.springframework.ai.zhipuai.ZhiPuAiImageModel; @@ -41,6 +42,7 @@ /** * @author Geng Rong + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "ZHIPU_AI_API_KEY", matches = ".*") public class ZhiPuAiAutoConfigurationIT { @@ -52,7 +54,7 @@ public class ZhiPuAiAutoConfigurationIT { @Test void generate() { - this.contextRunner.withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { ZhiPuAiChatModel chatModel = context.getBean(ZhiPuAiChatModel.class); ChatResponse response = chatModel.call(new Prompt("Hello", ChatOptions.builder().build())); @@ -63,7 +65,7 @@ void generate() { @Test void generateStreaming() { - this.contextRunner.withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { ZhiPuAiChatModel chatModel = context.getBean(ZhiPuAiChatModel.class); Flux responseFlux = chatModel @@ -81,7 +83,7 @@ void generateStreaming() { @Test void embedding() { - this.contextRunner.withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { ZhiPuAiEmbeddingModel embeddingModel = context.getBean(ZhiPuAiEmbeddingModel.class); @@ -99,7 +101,7 @@ void embedding() { @Test void generateImage() { - this.contextRunner.withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + this.contextRunner.withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .withPropertyValues("spring.ai.zhipuai.image.options.size=1024x1024") .run(context -> { ZhiPuAiImageModel ImageModel = context.getBean(ZhiPuAiImageModel.class); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiPropertiesTests.java index 57ac64fbde5..15bfca09096 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiPropertiesTests.java @@ -21,6 +21,7 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.ai.model.ModelOptionsUtils; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.zhipuai.ZhiPuAiChatModel; import org.springframework.ai.zhipuai.ZhiPuAiEmbeddingModel; import org.springframework.ai.zhipuai.ZhiPuAiImageModel; @@ -35,6 +36,7 @@ * * @author Geng Rong * @author YunKui Lu + * @author Issam El-atif */ public class ZhiPuAiPropertiesTests { @@ -48,7 +50,7 @@ public void chatProperties() { "spring.ai.zhipuai.chat.options.model=MODEL_XYZ", "spring.ai.zhipuai.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(ZhiPuAiChatProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -76,7 +78,7 @@ public void chatOverrideConnectionProperties() { "spring.ai.zhipuai.chat.options.model=MODEL_XYZ", "spring.ai.zhipuai.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(ZhiPuAiChatProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -101,7 +103,7 @@ public void embeddingProperties() { "spring.ai.zhipuai.api-key=abc123", "spring.ai.zhipuai.embedding.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(ZhiPuAiEmbeddingProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -127,7 +129,7 @@ public void embeddingOverrideConnectionProperties() { "spring.ai.zhipuai.embedding.api-key=456", "spring.ai.zhipuai.embedding.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { var embeddingProperties = context.getBean(ZhiPuAiEmbeddingProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -150,7 +152,7 @@ public void imageProperties() { "spring.ai.zhipuai.api-key=abc123", "spring.ai.zhipuai.image.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(ZhiPuAiImageProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -175,7 +177,7 @@ public void imageOverrideConnectionProperties() { "spring.ai.zhipuai.image.api-key=456", "spring.ai.zhipuai.image.options.model=MODEL_XYZ") // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(ZhiPuAiImageProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -240,7 +242,7 @@ public void chatOptionsTest() { "spring.ai.zhipuai.chat.options.thinking.type=disabled" ) // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(ZhiPuAiChatProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -286,7 +288,7 @@ public void embeddingOptionsTest() { "spring.ai.zhipuai.embedding.options.user=userXYZ" ) // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); var embeddingProperties = context.getBean(ZhiPuAiEmbeddingProperties.class); @@ -308,7 +310,7 @@ public void imageOptionsTest() { "spring.ai.zhipuai.image.options.user=userXYZ" ) // @formatter:on - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .run(context -> { var imageProperties = context.getBean(ZhiPuAiImageProperties.class); var connectionProperties = context.getBean(ZhiPuAiConnectionProperties.class); @@ -326,7 +328,7 @@ void embeddingActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL", "spring.ai.model.embedding=none") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiEmbeddingProperties.class)).isEmpty(); assertThat(context.getBeansOfType(ZhiPuAiEmbeddingModel.class)).isEmpty(); @@ -334,7 +336,7 @@ void embeddingActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ZhiPuAiEmbeddingModel.class)).isNotEmpty(); @@ -343,7 +345,7 @@ void embeddingActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL", "spring.ai.model.embedding=zhipuai") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiEmbeddingAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiEmbeddingAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiEmbeddingProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ZhiPuAiEmbeddingModel.class)).isNotEmpty(); @@ -355,7 +357,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL", "spring.ai.model.chat=none") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiChatProperties.class)).isEmpty(); assertThat(context.getBeansOfType(ZhiPuAiChatModel.class)).isEmpty(); @@ -363,7 +365,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ZhiPuAiChatModel.class)).isNotEmpty(); @@ -372,7 +374,7 @@ void chatActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL", "spring.ai.model.chat=zhipuai") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ZhiPuAiChatModel.class)).isNotEmpty(); @@ -385,7 +387,7 @@ void imageActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL", "spring.ai.model.image=none") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiImageProperties.class)).isEmpty(); assertThat(context.getBeansOfType(ZhiPuAiImageModel.class)).isEmpty(); @@ -393,7 +395,7 @@ void imageActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiImageProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ZhiPuAiImageModel.class)).isNotEmpty(); @@ -402,7 +404,7 @@ void imageActivation() { new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.api-key=API_KEY", "spring.ai.zhipuai.base-url=TEST_BASE_URL", "spring.ai.model.image=zhipuai") - .withConfiguration(ZhiPuAiITUtil.zhiPuAiAutoConfig(ZhiPuAiImageAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiImageAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(ZhiPuAiImageProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(ZhiPuAiImageModel.class)).isNotEmpty(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackInPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackInPromptIT.java index 8470c188f33..d217096b832 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackInPromptIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackInPromptIT.java @@ -31,8 +31,8 @@ import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiITUtil; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.zhipuai.ZhiPuAiChatModel; import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -41,6 +41,7 @@ /** * @author Geng Rong + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "ZHIPU_AI_API_KEY", matches = ".*") public class FunctionCallbackInPromptIT { @@ -49,7 +50,7 @@ public class FunctionCallbackInPromptIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.apiKey=" + System.getenv("ZHIPU_AI_API_KEY")) - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)); + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)); @Test void functionCallTest() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java index 8634afd524c..0a3213e971d 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java @@ -33,7 +33,7 @@ import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.tool.ToolCallingChatOptions; import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiITUtil; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.zhipuai.ZhiPuAiChatModel; import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -45,6 +45,7 @@ /** * @author Geng Rong + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "ZHIPU_AI_API_KEY", matches = ".*") class FunctionCallbackWithPlainFunctionBeanIT { @@ -53,7 +54,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.apiKey=" + System.getenv("ZHIPU_AI_API_KEY")) - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/ZhipuAiFunctionCallbackIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/ZhipuAiFunctionCallbackIT.java index bcea38585cf..171c1f979bf 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/ZhipuAiFunctionCallbackIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/tool/ZhipuAiFunctionCallbackIT.java @@ -31,9 +31,9 @@ import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiITUtil; import org.springframework.ai.tool.ToolCallback; import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.utils.SpringAiTestAutoConfigurations; import org.springframework.ai.zhipuai.ZhiPuAiChatModel; import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -44,6 +44,7 @@ /** * @author Geng Rong + * @author Issam El-atif */ @EnabledIfEnvironmentVariable(named = "ZHIPU_AI_API_KEY", matches = ".*") public class ZhipuAiFunctionCallbackIT { @@ -52,7 +53,7 @@ public class ZhipuAiFunctionCallbackIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.zhipuai.apiKey=" + System.getenv("ZHIPU_AI_API_KEY")) - .withConfiguration(ZhiPuAiITUtil.zhiPuAiToolAutoConfig(ZhiPuAiChatAutoConfiguration.class)) + .withConfiguration(SpringAiTestAutoConfigurations.of(ZhiPuAiChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/spring-ai-test/src/main/java/org/springframework/ai/utils/SpringAiTestAutoConfigurations.java b/spring-ai-test/src/main/java/org/springframework/ai/utils/SpringAiTestAutoConfigurations.java index 628006485e6..6ad89ec2797 100644 --- a/spring-ai-test/src/main/java/org/springframework/ai/utils/SpringAiTestAutoConfigurations.java +++ b/spring-ai-test/src/main/java/org/springframework/ai/utils/SpringAiTestAutoConfigurations.java @@ -34,6 +34,7 @@ *

* * @author Issam El-atif + * @since 1.1.0 * @see AutoConfigurations */ public final class SpringAiTestAutoConfigurations {