This is an automated email from the ASF dual-hosted git repository.
fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 9796b7c0b71f Fix langchain4j agent test
9796b7c0b71f is described below
commit 9796b7c0b71f98b172102bdf3ffdefd4e248c6e2
Author: Croway <[email protected]>
AuthorDate: Wed Jan 21 17:26:28 2026 +0100
Fix langchain4j agent test
---
.../LangChain4jAgentGuardrailsIntegrationIT.java | 5 ++++-
.../integration/LangChain4jAgentMcpToolsIT.java | 13 ++++++++-----
.../LangChain4jAgentMultimodalityIT.java | 12 ++++++++++++
.../integration/LangChain4jAgentWrappedFileIT.java | 18 +++++++++++++-----
.../agent/pojos/TestJsonOutputGuardrail.java | 21 +++++++++++++++++++++
5 files changed, 58 insertions(+), 11 deletions(-)
diff --git
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentGuardrailsIntegrationIT.java
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentGuardrailsIntegrationIT.java
index 98fc914c8e8c..75921509abea 100644
---
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentGuardrailsIntegrationIT.java
+++
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentGuardrailsIntegrationIT.java
@@ -142,10 +142,13 @@ public class LangChain4jAgentGuardrailsIntegrationIT
extends CamelTestSupport {
@Test
void testAgentWithJsonOutputGuardrailFailure() throws InterruptedException
{
+ // Disable reprompting so the guardrail fails immediately with fatal
error
+ TestJsonOutputGuardrail.setAllowReprompt(false);
+
MockEndpoint mockEndpoint =
this.context.getEndpoint("mock:agent-response", MockEndpoint.class);
mockEndpoint.expectedMessageCount(0); // No message should reach the
endpoint due to guardrail failure
- String nonJsonRequest = "Tell me a simple story about a cat in one
sentence.";
+ String nonJsonRequest = "Tell me a simple story about a cat in one
sentence";
// Expect an exception due to guardrail failure
Exception exception = assertThrows(Exception.class, () -> {
diff --git
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMcpToolsIT.java
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMcpToolsIT.java
index 6fff04f75f7a..eaec43962cfa 100644
---
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMcpToolsIT.java
+++
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMcpToolsIT.java
@@ -72,14 +72,15 @@ public class LangChain4jAgentMcpToolsIT extends
CamelTestSupport {
super.setupResources();
chatModel = OLLAMA != null ? ModelHelper.loadChatModel(OLLAMA) :
ModelHelper.loadFromEnv();
- // Initialize tempDirPat
- tempDirPath = tempDir.toString();
+ // Initialize tempDirPath - use toRealPath() to resolve symlinks
(e.g., /var -> /private/var on macOS)
+ // This is needed because the MCP filesystem server resolves symlinks
internally
+ tempDirPath = tempDir.toRealPath().toString();
// Create test file directly
try {
Path testFile = tempDir.resolve("camel-mcp-test.txt");
Files.write(testFile, TEST_FILE_CONTENT.getBytes());
- testFilePath = testFile.toString();
+ testFilePath = testFile.toRealPath().toString();
} catch (IOException e) {
throw new RuntimeException("Failed to create test file", e);
}
@@ -123,7 +124,8 @@ public class LangChain4jAgentMcpToolsIT extends
CamelTestSupport {
mockEndpoint.expectedMessageCount(1);
String response = template.requestBody("direct:chat",
- "Use your available tools to tell me what is the content of
camel-mcp-test.txt file?", String.class);
+ "Use your available tools to tell me what is the content of
the file at " + testFilePath + " ?",
+ String.class);
mockEndpoint.assertIsSatisfied();
assertNotNull(response, "AI response should not be null");
@@ -154,7 +156,8 @@ public class LangChain4jAgentMcpToolsIT extends
CamelTestSupport {
BiPredicate<McpClient, ToolSpecification> securityFilter = (client,
toolSpec) -> {
String toolName = toolSpec.name().toLowerCase();
// Only allow read operations for safety
- return toolName.contains("read") || toolName.contains("list") ||
toolName.contains("get");
+ return toolName.contains("search") || toolName.contains("read") ||
toolName.contains("list")
+ || toolName.contains("get");
};
// Create agent configuration with MCP clients and filter
diff --git
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMultimodalityIT.java
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMultimodalityIT.java
index a2ac1014d928..1deb09da84af 100644
---
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMultimodalityIT.java
+++
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentMultimodalityIT.java
@@ -33,11 +33,13 @@ import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.infra.ollama.services.OllamaService;
import org.apache.camel.test.infra.ollama.services.OllamaServiceFactory;
import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
/**
* Integration tests for multimodal content support in the LangChain4j Agent
component. Tests the ability to send both
@@ -61,6 +63,16 @@ public class LangChain4jAgentMultimodalityIT extends
CamelTestSupport {
chatModel = OLLAMA != null ? ModelHelper.loadChatModel(OLLAMA) :
ModelHelper.loadFromEnv();
}
+ @BeforeEach
+ void skipIfOllama() {
+ boolean isOllama = OLLAMA != null ||
"ollama".equals(System.getenv(ModelHelper.MODEL_PROVIDER));
+ assumeFalse(isOllama,
+ "Skipping multimodality tests with Ollama: LangChain4j's
Ollama provider does not support " +
+ "multiple content blocks in a single
UserMessage. The provider's InternalOllamaHelper.toText() " +
+ "calls UserMessage.singleText() which requires
exactly one TextContent. " +
+ "Use OpenAI or Gemini providers for multimodal
content testing.");
+ }
+
/**
* Tests sending a message with TextContent. This validates that the
Content parameter works correctly with simple
* text content.
diff --git
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentWrappedFileIT.java
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentWrappedFileIT.java
index b2bff35d4157..bbe6c190a9d3 100644
---
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentWrappedFileIT.java
+++
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/integration/LangChain4jAgentWrappedFileIT.java
@@ -32,6 +32,8 @@ import
org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
/**
* Integration tests for WrappedFile support in the LangChain4j Agent
component. Tests the ability to process files from
@@ -58,11 +60,17 @@ public class LangChain4jAgentWrappedFileIT extends
CamelTestSupport {
protected void setupResources() throws Exception {
super.setupResources();
- if (!ModelHelper.hasEnvironmentConfiguration()) {
- throw new IllegalStateException(
- "This test requires environment variables: API_KEY,
MODEL_PROVIDER. "
- + "Optionally: MODEL_BASE_URL,
MODEL_NAME");
- }
+ // Skip if no environment configuration - this test requires external
API providers
+ assumeTrue(ModelHelper.hasEnvironmentConfiguration(),
+ "Skipping: This test requires environment variables: API_KEY,
MODEL_PROVIDER. " +
+ "Optionally:
MODEL_BASE_URL, MODEL_NAME");
+
+ // Skip if using Ollama - it doesn't support multimodal content
+ assumeFalse("ollama".equals(System.getenv(ModelHelper.MODEL_PROVIDER)),
+ "Skipping wrapped file tests with Ollama: LangChain4j's Ollama
provider does not support " +
+
"multimodal content (images, PDFs). The provider's InternalOllamaHelper
requires "
+
+
+
"single text content in UserMessage. Use OpenAI or Gemini providers for file
processing tests.");
chatModel = ModelHelper.loadFromEnv();
diff --git
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/pojos/TestJsonOutputGuardrail.java
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/pojos/TestJsonOutputGuardrail.java
index 48c1a825c1ea..1d63412e097d 100644
---
a/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/pojos/TestJsonOutputGuardrail.java
+++
b/components/camel-ai/camel-langchain4j-agent/src/test/java/org/apache/camel/component/langchain4j/agent/pojos/TestJsonOutputGuardrail.java
@@ -27,6 +27,7 @@ import dev.langchain4j.guardrail.OutputGuardrailResult;
public class TestJsonOutputGuardrail extends
JsonExtractorOutputGuardrail<Object> {
private static volatile boolean wasValidated = false;
+ private static volatile boolean allowReprompt = true;
public TestJsonOutputGuardrail() {
super(Object.class);
@@ -78,8 +79,28 @@ public class TestJsonOutputGuardrail extends
JsonExtractorOutputGuardrail<Object
return null;
}
+ @Override
+ protected OutputGuardrailResult invokeInvalidJson(AiMessage aiMessage,
String json) {
+ if (allowReprompt) {
+ // Default behavior: reprompt to get valid JSON
+ return super.invokeInvalidJson(aiMessage, json);
+ }
+ // Fail immediately without reprompting
+ return fatal("Output validation failed: Invalid JSON format");
+ }
+
+ /**
+ * Sets whether reprompting is allowed when JSON validation fails.
+ *
+ * @param allow true to allow reprompting (default), false to fail
immediately
+ */
+ public static void setAllowReprompt(boolean allow) {
+ allowReprompt = allow;
+ }
+
public static void reset() {
wasValidated = false;
+ allowReprompt = true;
}
/**