package com.xly.service; 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.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; /** skill 文件加载:5 个技能齐全、首行为用途、正文非空、模糊名可命中。 */ class SkillServiceTest { private final SkillService skills = new SkillService(null); // jdbc 未装配 → 按表不存在 → classpath 模式 @Test void allFiveSkillsLoadFromClasspath() { List all = skills.all(); assertEquals(5, all.size()); for (String name : new String[]{"查询数据", "新建报价", "新建单据", "修改记录", "单据状态操作"}) { SkillService.Skill s = skills.find(name); assertNotNull(s, name + " 必须存在"); assertTrue(s.brief().length() > 4, "首行=一句话用途"); assertTrue(s.body().contains("【技能:"), "正文为技能全文"); } } @Test void fuzzyNameMatches() { assertEquals("新建报价", skills.find("新建报价单").name(), "「新建报价单」→ 新建报价"); assertEquals("修改记录", skills.find("修改").name()); assertNull(skills.find("不存在的技能")); } @Test void indexHasOneLinePerSkill() { String idx = skills.indexLines(); assertEquals(5, idx.strip().split("\n").length); assertTrue(idx.contains("- 新建报价:")); } // ---------------- DB 全权模式(表存在开关) ---------------- private org.springframework.jdbc.core.JdbcTemplate jdbcWithTable(boolean exists) { org.springframework.jdbc.core.JdbcTemplate jdbc = org.mockito.Mockito.mock(org.springframework.jdbc.core.JdbcTemplate.class); org.mockito.Mockito.when(jdbc.queryForObject( org.mockito.ArgumentMatchers.contains("information_schema"), org.mockito.ArgumentMatchers.eq(Integer.class))) .thenReturn(exists ? 1 : 0); return jdbc; } @Test void tableExistsMeansDbOnlyEvenIfEmpty() { org.springframework.jdbc.core.JdbcTemplate jdbc = jdbcWithTable(true); org.mockito.Mockito.when(jdbc.queryForList(org.mockito.ArgumentMatchers.startsWith("SELECT sName"))) .thenReturn(java.util.List.of()); SkillService s = new SkillService(jdbc); assertTrue(s.all().isEmpty(), "空表 = 用户要的无技能场景,绝不回读 war 包"); assertTrue(s.indexLines().isBlank()); assertNull(s.find("新建报价")); } @Test void tableExistsLoadsCustomSkillsFromDb() { org.springframework.jdbc.core.JdbcTemplate jdbc = jdbcWithTable(true); org.mockito.Mockito.when(jdbc.queryForList(org.mockito.ArgumentMatchers.startsWith("SELECT sName"))) .thenReturn(java.util.List.of(java.util.Map.of( "sName", "自定义流程", "sBrief", "用户自定义", "sBody", "【技能:自定义流程】1. 步骤"))); SkillService s = new SkillService(jdbc); assertEquals(1, s.all().size(), "DB 有 1 行 = 只读这 1 行,不合并 war 包"); assertEquals("自定义流程", s.find("自定义").name()); } @Test void dbFailureDegradesToNoSkillsNotClasspath() { org.springframework.jdbc.core.JdbcTemplate jdbc = org.mockito.Mockito.mock(org.springframework.jdbc.core.JdbcTemplate.class); org.mockito.Mockito.when(jdbc.queryForObject( org.mockito.ArgumentMatchers.anyString(), org.mockito.ArgumentMatchers.eq(Integer.class))) .thenThrow(new RuntimeException("db down")); SkillService s = new SkillService(jdbc); assertTrue(s.all().isEmpty(), "DB 故障按无技能降级,绝不回落 war 包"); } @Test void tableAbsentFallsBackToClasspath() { SkillService s = new SkillService(jdbcWithTable(false)); assertEquals(5, s.all().size(), "表不存在 → 读 war 包内置技能"); } }