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 85307386b9 feat(ut): add ai plugin unit test (#6078)
85307386b9 is described below
commit 85307386b9f3412a5afc6c504fc10bf64c859892
Author: shown <[email protected]>
AuthorDate: Sat Aug 2 12:21:19 2025 +0800
feat(ut): add ai plugin unit test (#6078)
* fix
Signed-off-by: shown.Ji <[email protected]>
* fix
Signed-off-by: shown.Ji <[email protected]>
---------
Signed-off-by: shown.Ji <[email protected]>
---
.../request/AiRequestTransformerPlugin.java | 15 ++-
.../transformer/request/cache/ChatClientCache.java | 5 +-
.../handler/AiRequestTransformerPluginHandler.java | 1 -
.../request/AiRequestTransformerPluginTest.java | 133 +++++++++++++++++++++
.../request/cache/ChatClientCacheTest.java | 83 +++++++++++++
.../AiRequestTransformerPluginHandlerTest.java | 99 +++++++++++++++
.../template/AiRequestTransformerTemplateTest.java | 124 +++++++++++++++++++
7 files changed, 452 insertions(+), 8 deletions(-)
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPlugin.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPlugin.java
index bbbce6593e..8232f7c4ed 100644
---
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPlugin.java
@@ -142,11 +142,17 @@ public class AiRequestTransformerPlugin extends
AbstractShenyuPlugin {
}
- private static String convertBodyJson(final String aiResponse) {
+ /**
+ * For unit test.
+ */
+ static String convertBodyJson(final String aiResponse) {
return extractJsonBodyFromHttpResponse(aiResponse);
}
- private static String convertBodyFormData(final String aiResponse) {
+ /**
+ * For unit test.
+ */
+ static String convertBodyFormData(final String aiResponse) {
Map<String, Object> formDataMap =
GsonUtils.getInstance().toObjectMap(extractJsonBodyFromHttpResponse(aiResponse));
return mapToFormUrlEncoded(formDataMap);
}
@@ -212,7 +218,10 @@ public class AiRequestTransformerPlugin extends
AbstractShenyuPlugin {
return Mono.just(exchange);
}
- private static HttpHeaders extractHeadersFromAiResponse(final String
aiResponse) {
+ /**
+ * For unit test.
+ */
+ static HttpHeaders extractHeadersFromAiResponse(final String aiResponse) {
HttpHeaders headers = new HttpHeaders();
if (Objects.isNull(aiResponse) || aiResponse.isEmpty()) {
return headers;
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCache.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCache.java
index e7a21c1f4d..52d76370cb 100644
---
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCache.java
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCache.java
@@ -30,9 +30,6 @@ public class ChatClientCache {
private static final Map<String, ChatClient> CHAT_CLIENT_MAP = new
HashMap<>();
- public ChatClientCache() {
- }
-
/**
* Init.
*
@@ -78,13 +75,13 @@ public class ChatClientCache {
* The type Application config cache instance.
*/
static final class ApplicationConfigCacheInstance {
+
/**
* The Instance.
*/
static final ChatClientCache INSTANCE = new ChatClientCache();
private ApplicationConfigCacheInstance() {
-
}
}
}
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandler.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandler.java
index b84308d54a..3b59020fde 100644
---
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandler.java
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandler.java
@@ -15,7 +15,6 @@
* limitations under the License.
*/
-
package org.apache.shenyu.plugin.ai.transformer.request.handler;
import org.apache.shenyu.common.dto.PluginData;
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPluginTest.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPluginTest.java
new file mode 100644
index 0000000000..0d56a48fe0
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/AiRequestTransformerPluginTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.transformer.request;
+
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.dto.convert.plugin.AiRequestTransformerConfig;
+import org.apache.shenyu.common.dto.convert.rule.AiRequestTransformerHandle;
+import org.apache.shenyu.common.enums.AiModelProviderEnum;
+import org.apache.shenyu.plugin.ai.common.spring.ai.AiModelFactory;
+import
org.apache.shenyu.plugin.ai.common.spring.ai.registry.AiModelFactoryRegistry;
+import org.apache.shenyu.plugin.ai.transformer.request.cache.ChatClientCache;
+import org.apache.shenyu.plugin.api.ShenyuPluginChain;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.chat.client.ChatClient;
+import org.springframework.ai.chat.model.ChatModel;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class AiRequestTransformerPluginTest {
+
+ private AiModelFactoryRegistry aiModelFactoryRegistry;
+
+ private ChatClientCache chatClientCache;
+
+ private ShenyuPluginChain chain;
+
+ private AiRequestTransformerPlugin plugin;
+
+ @BeforeEach
+ void setUp() {
+
+ aiModelFactoryRegistry = mock(AiModelFactoryRegistry.class);
+ chatClientCache = mock(ChatClientCache.class);
+ chain = mock(ShenyuPluginChain.class);
+ plugin = new AiRequestTransformerPlugin(Collections.emptyList(),
aiModelFactoryRegistry);
+ }
+
+ @Test
+ void testDoExecuteWithMissingConfigurations() {
+
+ MockServerWebExchange exchange =
MockServerWebExchange.from(MockServerHttpRequest.post("/test").build());
+ SelectorData selector = new SelectorData();
+ RuleData rule = new RuleData();
+
+ when(chain.execute(exchange)).thenReturn(Mono.empty());
+
+ StepVerifier.create(plugin.doExecute(exchange, chain, selector, rule))
+ .verifyComplete();
+
+ verify(chain).execute(exchange);
+ }
+
+ @Test
+ void testDoExecuteWithValidConfigurations() {
+
+ AiRequestTransformerConfig config = new AiRequestTransformerConfig();
+ config.setBaseUrl("http://test.com");
+ config.setApiKey("test-api-key");
+ config.setProvider("TEST_PROVIDER");
+ config.setModel("test-model");
+
+ AiRequestTransformerHandle handle = new AiRequestTransformerHandle();
+ handle.setProvider("TEST_PROVIDER");
+ handle.setBaseUrl("http://test.com");
+ handle.setApiKey("test-api-key");
+ handle.setModel("test-model");
+
+ ChatClient mockClient = mock(ChatClient.class);
+ ChatModel mockModel = mock(ChatModel.class);
+ AiModelFactory mockFactory = mock(AiModelFactory.class);
+
+ MockServerWebExchange exchange =
MockServerWebExchange.from(MockServerHttpRequest.post("/test")
+ .header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE)
+ .body("{\"key\":\"value\"}"));
+
when(aiModelFactoryRegistry.getFactory(AiModelProviderEnum.getByName("TEST_PROVIDER"))).thenReturn(mockFactory);
+ when(mockFactory.createAiModel(any())).thenReturn(mockModel);
+ when(chatClientCache.getClient("default")).thenReturn(mockClient);
+ when(chain.execute(exchange)).thenReturn(Mono.empty());
+
+ SelectorData selector = new SelectorData();
+ RuleData rule = new RuleData();
+ StepVerifier.create(plugin.doExecute(exchange, chain, selector, rule))
+ .verifyComplete();
+
+ verify(chain).execute(exchange);
+ }
+
+ @Test
+ void testConvertBodyJson() {
+
+ String aiResponse = "HTTP/1.1 200 OK\nContent-Type:
application/json\n\n{\"key\":\"value\"}";
+ String result = AiRequestTransformerPlugin.convertBodyJson(aiResponse);
+ assertEquals("{\"key\":\"value\"}", result);
+ }
+
+ @Test
+ void testExtractHeadersFromAiResponse() {
+
+ String aiResponse = "HTTP/1.1 200 OK\nContent-Type:
application/json\nAuthorization: Bearer token\n\n{\"key\":\"value\"}";
+ HttpHeaders headers =
AiRequestTransformerPlugin.extractHeadersFromAiResponse(aiResponse);
+ assertEquals("application/json",
headers.getFirst(HttpHeaders.CONTENT_TYPE));
+ assertEquals("Bearer token",
headers.getFirst(HttpHeaders.AUTHORIZATION));
+ }
+}
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCacheTest.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCacheTest.java
new file mode 100644
index 0000000000..7fee0d68e6
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/cache/ChatClientCacheTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.transformer.request.cache;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.chat.client.ChatClient;
+import org.springframework.ai.chat.model.ChatModel;
+import org.springframework.ai.openai.OpenAiChatModel;
+import org.springframework.ai.openai.api.OpenAiApi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.mockito.Mockito.mock;
+
+class ChatClientCacheTest {
+
+ private ChatClientCache chatClientCache;
+
+ @BeforeEach
+ void setUp() {
+
+ chatClientCache = ChatClientCache.getInstance();
+ }
+
+ @Test
+ void testGetInstance() {
+
+ ChatClientCache instance1 = ChatClientCache.getInstance();
+ ChatClientCache instance2 = ChatClientCache.getInstance();
+ assertNotNull(instance1, "Instance should not be null");
+ assertSame(instance1, instance2, "Instances should be the same
(singleton)");
+ }
+
+ @Test
+ void testInitAndGetClient() {
+
+ ChatModel chatModel = OpenAiChatModel
+ .builder()
+ .openAiApi(
+ OpenAiApi.builder()
+ .apiKey("test-ak")
+ .build()
+ ).build();
+
+ String ruleId = "testRuleId";
+ ChatClient chatClient = chatClientCache.init(ruleId, chatModel);
+ assertNotNull(chatClient, "ChatClient should not be null");
+
+ ChatClient retrievedClient = chatClientCache.getClient(ruleId);
+ assertNotNull(retrievedClient, "Retrieved ChatClient should not be
null");
+ }
+
+ @Test
+ void testDestroyClient() {
+
+ String ruleId = "testRuleId";
+ ChatModel chatModel = mock(ChatModel.class);
+
+ chatClientCache.init(ruleId, chatModel);
+ assertNotNull(chatClientCache.getClient(ruleId), "ChatClient should
exist before destruction");
+
+ chatClientCache.destroyClient(ruleId);
+ assertNull(chatClientCache.getClient(ruleId), "ChatClient should be
null after destruction");
+ }
+
+}
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandlerTest.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandlerTest.java
new file mode 100644
index 0000000000..7888a7b3da
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/handler/AiRequestTransformerPluginHandlerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.transformer.request.handler;
+
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.convert.rule.AiRequestTransformerHandle;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
+import
org.apache.shenyu.plugin.ai.common.spring.ai.registry.AiModelFactoryRegistry;
+import org.apache.shenyu.plugin.ai.transformer.request.cache.ChatClientCache;
+import org.apache.shenyu.plugin.base.cache.CommonHandleCache;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
+import org.junit.jupiter.api.BeforeEach;
+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.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+class AiRequestTransformerPluginHandlerTest {
+
+ private AiModelFactoryRegistry aiModelFactoryRegistry;
+
+ private ChatClientCache chatClientCache;
+
+ private AiRequestTransformerPluginHandler pluginHandler;
+
+ @BeforeEach
+ void setUp() {
+ chatClientCache = ChatClientCache.getInstance();
+ aiModelFactoryRegistry = mock(AiModelFactoryRegistry.class);
+ pluginHandler = new
AiRequestTransformerPluginHandler(aiModelFactoryRegistry);
+ }
+
+ @Test
+ void testHandlerPluginWithInvalidData() {
+
+ PluginData pluginData = new PluginData();
+ pluginData.setEnabled(true);
+ pluginData.setConfig(null);
+
+ pluginHandler.handlerPlugin(pluginData);
+
+ verifyNoInteractions(aiModelFactoryRegistry);
+ }
+
+ @Test
+ void testHandlerRule() {
+
+ RuleData ruleData = new RuleData();
+ ruleData.setId("rule1");
+ AiRequestTransformerHandle handle = new AiRequestTransformerHandle();
+ handle.setProvider("TEST_PROVIDER");
+ ruleData.setHandle(GsonUtils.getInstance().toJson(handle));
+
+ pluginHandler.handlerRule(ruleData);
+
+ CommonHandleCache<String, AiRequestTransformerHandle> cache =
AiRequestTransformerPluginHandler.CACHED_HANDLE.get();
+ assertNotNull(cache.obtainHandle(CacheKeyUtils.INST.getKey(ruleData)));
+ }
+
+ @Test
+ void testRemoveRule() {
+
+ RuleData ruleData = new RuleData();
+ ruleData.setId("rule1");
+ AiRequestTransformerHandle handle = new AiRequestTransformerHandle();
+ handle.setProvider("TEST_PROVIDER");
+ ruleData.setHandle(GsonUtils.getInstance().toJson(handle));
+
+ pluginHandler.removeRule(ruleData);
+
+ CommonHandleCache<String, AiRequestTransformerHandle> cache =
AiRequestTransformerPluginHandler.CACHED_HANDLE.get();
+ assertNull(cache.obtainHandle(CacheKeyUtils.INST.getKey(ruleData)));
+ }
+
+ @Test
+ void testPluginNamed() {
+ assertEquals(PluginEnum.AI_REQUEST_TRANSFORMER.getName(),
pluginHandler.pluginNamed());
+ }
+}
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/template/AiRequestTransformerTemplateTest.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/template/AiRequestTransformerTemplateTest.java
new file mode 100644
index 0000000000..5760e6b01b
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-request-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/request/template/AiRequestTransformerTemplateTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.transformer.request.template;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class AiRequestTransformerTemplateTest {
+
+ @Test
+ void testAssembleMessageWithJsonBody() {
+
+ String jsonBody = "{\"key\":\"value\"}";
+
+ ServerHttpRequest request = MockServerHttpRequest.post("/")
+ .contentType(MediaType.APPLICATION_JSON)
+ .body(jsonBody);
+
+ String userContent = "Test user content";
+ AiRequestTransformerTemplate template = new
AiRequestTransformerTemplate(userContent, request);
+
+ Mono<String> result = template.assembleMessage();
+
+ StepVerifier.create(result)
+ .assertNext(message -> {
+ assertNotNull(message, "Message should not be null");
+ assertTrue(message.contains("system_prompt"), "Message
should contain system_prompt");
+ assertTrue(message.contains("user_prompt"), "Message
should contain user_prompt");
+ assertTrue(message.contains("key"), "Message should
contain JSON body key");
+ })
+ .verifyComplete();
+ }
+
+ @Test
+ void testAssembleMessageWithFormUrlEncodedBody() {
+
+ String formBody = "key1=value1&key2=value2";
+ String userContent = "Test user content";
+ ServerHttpRequest request = MockServerHttpRequest.post("/")
+ .contentType(MediaType.APPLICATION_FORM_URLENCODED)
+ .body(formBody);
+
+ AiRequestTransformerTemplate template = new
AiRequestTransformerTemplate(userContent, request);
+
+ Mono<String> result = template.assembleMessage();
+
+ StepVerifier.create(result)
+ .assertNext(message -> {
+ assertNotNull(message, "Message should not be null");
+ assertTrue(message.contains("system_prompt"), "Message
should contain system_prompt");
+ assertTrue(message.contains("user_prompt"), "Message
should contain user_prompt");
+ assertTrue(message.contains("key1"), "Message should
contain form data key1");
+ assertTrue(message.contains("value1"), "Message should
contain form data value1");
+ })
+ .verifyComplete();
+ }
+
+ @Test
+ void testAssembleMessageWithEmptyBody() {
+
+ String userContent = "Test user content";
+ ServerHttpRequest request = MockServerHttpRequest.post("/")
+ .contentType(MediaType.APPLICATION_JSON)
+ .body("");
+ AiRequestTransformerTemplate template = new
AiRequestTransformerTemplate(userContent, request);
+
+ Mono<String> result = template.assembleMessage();
+
+ StepVerifier.create(result)
+ .assertNext(message -> {
+ assertNotNull(message, "Message should not be null");
+ assertTrue(message.contains("system_prompt"), "Message
should contain system_prompt");
+ assertTrue(message.contains("user_prompt"), "Message
should contain user_prompt");
+ })
+ .verifyComplete();
+ }
+
+ @Test
+ void testAssembleMessageWithHeaders() {
+
+ String userContent = "Test user content";
+ ServerHttpRequest request = MockServerHttpRequest.post("/")
+ .header(HttpHeaders.AUTHORIZATION, "Bearer token")
+ .header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE)
+ .body("");
+
+ AiRequestTransformerTemplate template = new
AiRequestTransformerTemplate(userContent, request);
+
+ Mono<String> result = template.assembleMessage();
+
+ StepVerifier.create(result)
+ .assertNext(message -> {
+ assertNotNull(message, "Message should not be null");
+ assertTrue(message.contains("system_prompt"), "Message
should contain system_prompt");
+ assertTrue(message.contains("user_prompt"), "Message
should contain user_prompt");
+ assertTrue(message.contains("Authorization"), "Message
should contain Authorization header");
+ assertTrue(message.contains("Bearer token"), "Message
should contain Authorization value");
+ })
+ .verifyComplete();
+ }
+}