This is an automated email from the ASF dual-hosted git repository. liuhongyu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push: new 319ca4fd9f feat(ut): add ai plugin unit test (#6069) 319ca4fd9f is described below commit 319ca4fd9f824625ec609284d390f0236cdb3722 Author: shown <yuluo08290...@gmail.com> AuthorDate: Tue Jul 29 10:45:00 2025 +0800 feat(ut): add ai plugin unit test (#6069) Signed-off-by: shown.Ji <yuluo08290...@gmail.com> Co-authored-by: aias00 <liuhon...@apache.org> --- .../ai/factory/DeepSeekModelFactoryTest.java | 67 ++++++++++++++++++ .../spring/ai/factory/OpenAiModelFactoryTest.java | 67 ++++++++++++++++++ .../ai/registry/AiModelFactoryRegistryTest.java | 66 ++++++++++++++++++ .../ai/common/strategy/AiModelFactoryTest.java | 45 ++++++++++++ .../ai/common/strategy/openai/OpenAITest.java | 81 ++++++++++++++++++++++ 5 files changed, 326 insertions(+) diff --git a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/factory/DeepSeekModelFactoryTest.java b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/factory/DeepSeekModelFactoryTest.java new file mode 100644 index 0000000000..a706769640 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/factory/DeepSeekModelFactoryTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.shenyu.plugin.ai.common.spring.ai.factory; + +import org.apache.shenyu.common.enums.AiModelProviderEnum; +import org.apache.shenyu.plugin.ai.common.config.AiCommonConfig; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class DeepSeekModelFactoryTest { + + private DeepSeekModelFactory factory; + + @BeforeEach + void setUp() { + factory = new DeepSeekModelFactory(); + } + + @Test + void testCreateAiModel() { + AiCommonConfig config = mock(AiCommonConfig.class); + when(config.getBaseUrl()).thenReturn("https://api.deepseek.com"); + when(config.getApiKey()).thenReturn("test-api-key"); + when(config.getModel()).thenReturn("deepseek-model"); + when(config.getTemperature()).thenReturn(0.8); + when(config.getMaxTokens()).thenReturn(150); + + ChatModel chatModel = factory.createAiModel(config); + + assertNotNull(chatModel); + assertTrue(chatModel instanceof DeepSeekChatModel); + } + + @Test + void testSupportsWithDeepSeek() { + assertTrue(factory.supports(AiModelProviderEnum.DEEP_SEEK)); + } + + @Test + void testSupportsWithOtherModelType() { + assertFalse(factory.supports(AiModelProviderEnum.OPEN_AI)); + } + +} diff --git a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/factory/OpenAiModelFactoryTest.java b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/factory/OpenAiModelFactoryTest.java new file mode 100644 index 0000000000..d2ab4fc724 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/factory/OpenAiModelFactoryTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.shenyu.plugin.ai.common.spring.ai.factory; + +import org.apache.shenyu.common.enums.AiModelProviderEnum; +import org.apache.shenyu.plugin.ai.common.config.AiCommonConfig; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.openai.OpenAiChatModel; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class OpenAiModelFactoryTest { + + private OpenAiModelFactory factory; + + @BeforeEach + void setUp() { + factory = new OpenAiModelFactory(); + } + + @Test + void testCreateAiModel() { + AiCommonConfig config = mock(AiCommonConfig.class); + when(config.getBaseUrl()).thenReturn("https://api.openai.com"); + when(config.getApiKey()).thenReturn("test-api-key"); + when(config.getModel()).thenReturn("gpt-3.5-turbo"); + when(config.getTemperature()).thenReturn(0.7); + when(config.getMaxTokens()).thenReturn(100); + + ChatModel chatModel = factory.createAiModel(config); + + assertNotNull(chatModel); + assertTrue(chatModel instanceof OpenAiChatModel); + } + + @Test + void testSupportsWithOpenAi() { + assertTrue(factory.supports(AiModelProviderEnum.OPEN_AI)); + } + + @Test + void testSupportsWithOtherModelType() { + assertFalse(factory.supports(AiModelProviderEnum.DEEP_SEEK)); + } + +} diff --git a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/registry/AiModelFactoryRegistryTest.java b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/registry/AiModelFactoryRegistryTest.java new file mode 100644 index 0000000000..02e873fa14 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/spring/ai/registry/AiModelFactoryRegistryTest.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.shenyu.plugin.ai.common.spring.ai.registry; + +import org.apache.shenyu.common.enums.AiModelProviderEnum; +import org.apache.shenyu.plugin.ai.common.spring.ai.AiModelFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class AiModelFactoryRegistryTest { + + private AiModelFactoryRegistry registry; + + private AiModelFactory supportedFactory; + + private AiModelFactory unsupportedFactory; + + @BeforeEach + void setUp() { + supportedFactory = mock(AiModelFactory.class); + when(supportedFactory.supports(AiModelProviderEnum.OPEN_AI)).thenReturn(true); + + unsupportedFactory = mock(AiModelFactory.class); + when(unsupportedFactory.supports(AiModelProviderEnum.OPEN_AI)).thenReturn(false); + + registry = new AiModelFactoryRegistry(List.of(supportedFactory, unsupportedFactory)); + } + + @Test + void testGetFactoryWithSupportedModelType() { + AiModelFactory factory = registry.getFactory(AiModelProviderEnum.OPEN_AI); + assertNotNull(factory); + assertEquals(supportedFactory, factory); + } + + @Test + void testGetFactoryWithUnsupportedModelType() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + registry.getFactory(AiModelProviderEnum.DEEP_SEEK); + }); + assertEquals("Unsupported AI model: DEEP_SEEK", exception.getMessage()); + } +} diff --git a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/strategy/AiModelFactoryTest.java b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/strategy/AiModelFactoryTest.java new file mode 100644 index 0000000000..10a3052d96 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/strategy/AiModelFactoryTest.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.shenyu.plugin.ai.common.strategy; + +import org.apache.shenyu.common.enums.AiModelProviderEnum; +import org.apache.shenyu.plugin.ai.common.strategy.openai.OpenAI; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class AiModelFactoryTest { + + @Test + void testCreateAiModelWithValidProvider() { + AiModel aiModel = AiModelFactory.createAiModel(AiModelProviderEnum.OPEN_AI); + assertNotNull(aiModel); + assertTrue(aiModel instanceof OpenAI); + } + + @Test + void testCreateAiModelWithNullProvider() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + AiModelFactory.createAiModel(null); + }); + assertEquals("not supported provider", exception.getMessage()); + } +} diff --git a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/strategy/openai/OpenAITest.java b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/strategy/openai/OpenAITest.java new file mode 100644 index 0000000000..38bc2a9edb --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-common/src/test/java/org/apache/shenyu/plugin/ai/common/strategy/openai/OpenAITest.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.shenyu.plugin.ai.common.strategy.openai; + +import org.apache.shenyu.plugin.ai.common.config.AiCommonConfig; +import org.apache.shenyu.plugin.api.ShenyuPluginChain; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.web.server.ServerWebExchange; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +class OpenAITest { + + private OpenAI openAI; + + private AiCommonConfig aiCommonConfig; + + private ServerWebExchange exchange; + + private ShenyuPluginChain chain; + + private List<HttpMessageReader<?>> messageReaders; + + @BeforeEach + void setUp() { + openAI = new OpenAI(); + aiCommonConfig = new AiCommonConfig(); + aiCommonConfig.setApiKey("test-api-key"); + aiCommonConfig.setModel("test-model"); + aiCommonConfig.setStream(true); + + exchange = mock(ServerWebExchange.class); + chain = mock(ShenyuPluginChain.class); + messageReaders = mock(List.class); + } + + @Test + void testGetCompletionTokensValidResponse() { + + String responseBody = "{\"usage\":{\"completion_tokens\":42}}"; + Long tokens = openAI.getCompletionTokens(responseBody); + assertEquals(42L, tokens); + } + + @Test + void testGetCompletionTokensInvalidResponse() { + + String responseBody = "{\"invalid\":\"data\"}"; + Long tokens = openAI.getCompletionTokens(responseBody); + assertEquals(0L, tokens); + } + + @Test + void testGetCompletionTokensEmptyResponse() { + + String responseBody = ""; + Long tokens = openAI.getCompletionTokens(responseBody); + assertEquals(0L, tokens); + } + +}