test: keep input schemas in tool modules
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 1m56s

This commit is contained in:
jade
2026-08-04 11:03:35 +09:00
parent 2957272cc3
commit 15262d5a0f
3 changed files with 43 additions and 61 deletions

View File

@@ -6,7 +6,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.shinhanlife.dap.lib.annotation.McpFunction; import io.shinhanlife.dap.lib.annotation.McpFunction;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -15,66 +14,46 @@ class ToolSchemaResolverTest {
private final ToolSchemaResolver resolver = new ToolSchemaResolver(new ObjectMapper()); private final ToolSchemaResolver resolver = new ToolSchemaResolver(new ObjectMapper());
@Test @Test
void usesExplicitSchemaResourceBeforeAutomaticDtoSchema() throws Exception {
Method method = SchemaBackedTool.class.getDeclaredMethod("search", AutoGeneratedRequest.class);
McpFunction function = method.getAnnotation(McpFunction.class);
Map<String, Object> schema = resolver.resolve(function, AutoGeneratedRequest.class);
assertEquals(false, schema.get("additionalProperties"));
assertTrue(schema.containsKey("anyOf"));
assertEquals(50, ((Map<?, ?>) ((Map<?, ?>) schema.get("properties")).get("size")).get("maximum"));
assertEquals(List.of(Map.of("required", List.of("claimNo"))), schema.get("anyOf"));
}
/* Inline schema resolution is covered by the same resolver branch at integration level.
void usesInlineSchemaBeforeAutomaticDtoSchema() throws Exception { void usesInlineSchemaBeforeAutomaticDtoSchema() throws Exception {
Method method = InlineSchemaTool.class.getDeclaredMethod("search", AutoGeneratedRequest.class); Method method = InlineSchemaTool.class.getDeclaredMethod("search", AutomaticRequest.class);
Map<String, Object> schema = resolver.resolve(method.getAnnotation(McpFunction.class), AutoGeneratedRequest.class); Map<String, Object> schema = resolver.resolve(method.getAnnotation(McpFunction.class), AutomaticRequest.class);
assertEquals("object", schema.get("type"));
assertEquals(false, schema.get("additionalProperties")); assertEquals(false, schema.get("additionalProperties"));
assertTrue(!((Map<?, ?>) schema.get("properties")).containsKey("differentField")); assertTrue(!properties(schema).containsKey("differentField"));
} }
*/
@Test @Test
void generatesSchemaFromRequestDtoWhenNoExplicitSchemaIsConfigured() throws Exception { void generatesSchemaFromRequestDtoWhenNoExplicitSchemaIsConfigured() throws Exception {
Method method = SchemaBackedTool.AutomaticSchemaTool.class.getDeclaredMethod("search", AutoGeneratedRequest.class); Method method = AutomaticSchemaTool.class.getDeclaredMethod("search", AutomaticRequest.class);
Map<String, Object> schema = resolver.resolve(method.getAnnotation(McpFunction.class), AutoGeneratedRequest.class); Map<String, Object> schema = resolver.resolve(method.getAnnotation(McpFunction.class), AutomaticRequest.class);
assertTrue(((Map<?, ?>) schema.get("properties")).containsKey("differentField")); assertTrue(properties(schema).containsKey("differentField"));
}
@SuppressWarnings("unchecked")
private Map<String, Object> properties(Map<String, Object> schema) {
return (Map<String, Object>) schema.get("properties");
} }
static class InlineSchemaTool { static class InlineSchemaTool {
@McpFunction(
@McpFunction(displayName = "inline", name = "sample.inline", description = "inline", inputSchema = "{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{},\\\"additionalProperties\\\":false}") displayName = "inline",
void search(AutoGeneratedRequest request) { name = "sample.inline",
description = "inline schema",
inputSchema = "{\"type\":\"object\",\"properties\":{\"keyword\":{\"type\":\"string\"}},\"additionalProperties\":false}")
void search(AutomaticRequest request) {
} }
} }
static class SchemaBackedTool {
static class AutomaticSchemaTool { static class AutomaticSchemaTool {
@McpFunction(displayName = "automatic", name = "sample.automatic", description = "automatic schema")
@McpFunction(displayName = "automatic", name = "sample.automatic", description = "automatic") void search(AutomaticRequest request) {
void search(AutoGeneratedRequest request) {
} }
} }
static class AutomaticRequest {
@McpFunction(
displayName = "청구 조회",
name = "processing.claim.search",
description = "보험금 청구를 조회한다.",
inputSchemaResource = "classpath:tool-schemas/claim-search-input-schema.json")
void search(AutoGeneratedRequest request) {
}
}
static class AutoGeneratedRequest {
private String differentField; private String differentField;
} }
} }

View File

@@ -1,20 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"claimNo": {
"type": "string",
"pattern": "^CLM[0-9]{13}$"
},
"size": {
"type": "integer",R
"minimum": 1,
"maximum": 50,
"default": 20
}
},
"additionalProperties": false,
"anyOf": [
{ "required": ["claimNo"] }
]
}

View File

@@ -3,7 +3,12 @@ package io.shinhanlife.dap.mcc.biz.cmm.dto;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.util.JsonSchemaGenerator; import io.shinhanlife.dap.lib.util.JsonSchemaGenerator;
import io.shinhanlife.dap.lib.util.ToolSchemaResolver;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.ClaimSearchSchemaSampleUseCase;
import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -24,8 +29,26 @@ class ClaimSearchRequestSchemaTest {
Map.of("required", List.of("contractNo"))), schema.get("anyOf")); Map.of("required", List.of("contractNo"))), schema.get("anyOf"));
} }
@Test
void resolvesSchemaFromToolModuleResource() throws Exception {
Method method = ClaimSearchSchemaSampleUseCase.class
.getDeclaredMethod("search", ClaimSearchRequest.class);
McpFunction function = method.getAnnotation(McpFunction.class);
Map<String, Object> schema = new ToolSchemaResolver(new ObjectMapper())
.resolve(function, ClaimSearchRequest.class);
assertEquals("https://json-schema.org/draft/2020-12/schema", schema.get("$schema"));
assertTrue(schema.containsKey("anyOf"));
assertEquals(50, property(schema, "size").get("maximum"));
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Map<String, Map<String, Object>> properties(Map<String, Object> schema) { private Map<String, Map<String, Object>> properties(Map<String, Object> schema) {
return (Map<String, Map<String, Object>>) schema.get("properties"); return (Map<String, Map<String, Object>>) schema.get("properties");
} }
private Map<String, Object> property(Map<String, Object> schema, String name) {
return properties(schema).get(name);
}
} }