package com.superbiz.agent.service; import com.superbiz.agent.dto.KnowledgeEntry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.springframework.test.util.ReflectionTestUtils; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import static org.junit.jupiter.api.Assertions.*; /** * KnowledgeIndexService 单元测试 */ class KnowledgeIndexServiceTest { private KnowledgeIndexService service; @TempDir Path tempDir; @BeforeEach void setUp() { service = new KnowledgeIndexService(); ReflectionTestUtils.setField(service, "knowledgeBasePath", tempDir.toString()); } @Test void testExactMatch_singleMatch() { // 准备测试数据 KnowledgeEntry entry = KnowledgeEntry.builder() .filePath("test.md") .title("Test") .keywords(List.of("ERR_TIMEOUT", "超时")) .summary("Test summary") .category("api") .build(); service.addToIndex(entry); // 测试匹配 List results = service.exactMatch("ERR_TIMEOUT"); assertEquals(1, results.size()); assertEquals("Test", results.get(0).getTitle()); } @Test void testExactMatch_caseInsensitive() { KnowledgeEntry entry = KnowledgeEntry.builder() .filePath("test.md") .keywords(List.of("ERR_TIMEOUT")) .build(); service.addToIndex(entry); // 小写查询应该匹配 List results = service.exactMatch("err_timeout"); assertEquals(1, results.size()); } @Test void testExactMatch_partialMatch() { KnowledgeEntry entry = KnowledgeEntry.builder() .filePath("test.md") .keywords(List.of("支付网关")) .build(); service.addToIndex(entry); // 包含关键词的查询应该匹配 List results = service.exactMatch("支付网关超时问题"); assertEquals(1, results.size()); } @Test void testExactMatch_multipleMatches() { KnowledgeEntry entry1 = KnowledgeEntry.builder() .filePath("doc1.md") .title("Doc 1") .keywords(List.of("超时")) .build(); KnowledgeEntry entry2 = KnowledgeEntry.builder() .filePath("doc2.md") .title("Doc 2") .keywords(List.of("超时", "错误")) .build(); service.addToIndex(entry1); service.addToIndex(entry2); // 应该匹配两个文档 List results = service.exactMatch("超时"); assertEquals(2, results.size()); } @Test void testExactMatch_noMatch() { KnowledgeEntry entry = KnowledgeEntry.builder() .filePath("test.md") .keywords(List.of("错误码")) .build(); service.addToIndex(entry); // 不匹配的查询 List results = service.exactMatch("限流"); assertEquals(0, results.size()); } @Test void testExactMatch_emptyQuery() { List results = service.exactMatch(""); assertEquals(0, results.size()); } @Test void testExactMatch_nullQuery() { List results = service.exactMatch(null); assertEquals(0, results.size()); } @Test void testReadDocument_success() throws Exception { // 创建测试文件 Path testFile = tempDir.resolve("test.md"); String content = "Test content line 1\nTest content line 2\n"; Files.writeString(testFile, content); // 读取文件 String result = service.readDocument(testFile.toString(), 100); assertNotNull(result); assertTrue(result.contains("Test content")); } @Test void testReadDocument_relativePathUnderBasePath() throws Exception { Path categoryDir = tempDir.resolve("payment"); Files.createDirectories(categoryDir); Path testFile = categoryDir.resolve("relative.md"); Files.writeString(testFile, "Relative content"); String result = service.readDocument("payment/relative.md", 100); assertEquals("Relative content", result); } @Test void testReadDocument_legacyPathAlreadyContainsBasePath() throws Exception { Path categoryDir = tempDir.resolve("payment"); Files.createDirectories(categoryDir); Path testFile = categoryDir.resolve("legacy.md"); Files.writeString(testFile, "Legacy content"); String result = service.readDocument(tempDir.getFileName() + "/payment/legacy.md", 100); assertEquals("Legacy content", result); } @Test void testReadDocument_exceedsMaxChars() throws Exception { // 创建超长内容 String longContent = "x".repeat(3000); Path testFile = tempDir.resolve("long.md"); Files.writeString(testFile, longContent); // 读取限制字符数 String result = service.readDocument(testFile.toString(), 2000); assertNotNull(result); assertEquals(2003, result.length()); // 2000 + "..." assertTrue(result.endsWith("...")); } @Test void testReadDocument_fileNotFound() { String result = service.readDocument("nonexistent.md", 100); assertNull(result); } @Test void testAddToIndex() { KnowledgeEntry entry = KnowledgeEntry.builder() .filePath("new.md") .title("New Document") .keywords(List.of("test")) .build(); service.addToIndex(entry); List results = service.exactMatch("test"); assertEquals(1, results.size()); assertEquals("New Document", results.get(0).getTitle()); } @Test void testRemoveFromIndex() { KnowledgeEntry entry = KnowledgeEntry.builder() .filePath("remove.md") .keywords(List.of("test")) .build(); service.addToIndex(entry); assertEquals(1, service.exactMatch("test").size()); service.removeFromIndex("remove.md"); assertEquals(0, service.exactMatch("test").size()); } @Test void testGetIndexSize() { assertEquals(0, service.getIndexSize()); service.addToIndex(KnowledgeEntry.builder() .filePath("doc1.md") .keywords(List.of("test")) .build()); assertEquals(1, service.getIndexSize()); service.addToIndex(KnowledgeEntry.builder() .filePath("doc2.md") .keywords(List.of("test")) .build()); assertEquals(2, service.getIndexSize()); } }