|
|
@@ -0,0 +1,124 @@
|
|
|
+package com.etotem.cfc.unit;
|
|
|
+
|
|
|
+import com.etotem.cfc.mapper.KnowledgeBaseSectionMapper;
|
|
|
+import com.etotem.cfc.service.UnifiedKnowledgeBaseService;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 低侧判读补丁块子键可查询验收(平台修改计划 T1 / L2-2,P0)。
|
|
|
+ *
|
|
|
+ * <p>验证 {@code 条件致病菌低侧判读补充(人工)} 作为统一知识库独立可查询子键:
|
|
|
+ * 判读铁律(U 型双向)/ 大肠杆菌偏低侧四机制 / 报告原文口径引用——供 L4 归因引擎
|
|
|
+ * 与合规门禁直接取用;KB 查询(getLowSideJudgmentPatch / getSection)须返回子键完整内容。
|
|
|
+ *
|
|
|
+ * <p>测试策略:mock 掉 DB(mapper 默认返回空/0,等效降级内存模式),
|
|
|
+ * 由 classpath 种子 {@code /knowledge-base/统一知识库.json} 加载后断言子键内容完整。
|
|
|
+ */
|
|
|
+class UnifiedKnowledgeBaseLowSidePatchTest {
|
|
|
+
|
|
|
+ private static final String MODULE = UnifiedKnowledgeBaseService.MODULE_LOW_SIDE_PATCH;
|
|
|
+ private static final String KEY_IRON_RULES = "判读铁律(U型双向)";
|
|
|
+ private static final String KEY_FOUR_MECHANISMS = "大肠杆菌(Escherichia coli)偏低侧影响";
|
|
|
+ private static final String KEY_REPORT_CALIBER = "报告原文引用(仅结构性口径,个人实测值不入库)";
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void lowSidePatch_独立可查询_返回完整子键内容() throws Exception {
|
|
|
+ UnifiedKnowledgeBaseService service = buildServiceFromSeed();
|
|
|
+
|
|
|
+ Map<String, Object> patch = service.getLowSideJudgmentPatch();
|
|
|
+ assertNotNull(patch, "低侧判读补丁块子键必须可从统一知识库查询");
|
|
|
+ assertEquals(patch, service.getSection(MODULE), "getLowSideJudgmentPatch 与 getSection 子键返回一致");
|
|
|
+
|
|
|
+ // 8 个顶层节完整存在(补丁说明/判读铁律/四机制/报告口径/分组矛盾/菌种综合信息/艾德范思参考/引用红线)
|
|
|
+ assertEquals(8, patch.size(), "子键须含完整 8 节");
|
|
|
+ assertTrue(patch.containsKey("补丁说明"), "应含补丁说明");
|
|
|
+ assertTrue(patch.containsKey(KEY_IRON_RULES), "应含判读铁律");
|
|
|
+ assertTrue(patch.containsKey(KEY_FOUR_MECHANISMS), "应含大肠杆菌偏低侧四机制");
|
|
|
+ assertTrue(patch.containsKey(KEY_REPORT_CALIBER), "应含报告原文口径引用");
|
|
|
+ assertTrue(patch.containsKey("引用红线"), "应含引用红线");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void lowSidePatch_判读铁律_含U型双向与不推荐补菌() throws Exception {
|
|
|
+ UnifiedKnowledgeBaseService service = buildServiceFromSeed();
|
|
|
+ Map<String, Object> iron = castMap(service.getLowSideJudgmentPatch().get(KEY_IRON_RULES));
|
|
|
+
|
|
|
+ assertEquals(5, iron.size(), "判读铁律 5 条:U 型双向/参考下限0/16S粒度/不推荐补菌/证据等级");
|
|
|
+ assertTrue(iron.containsKey("健康区间是范围而非单向"), "U 型双向:低就是好不成立");
|
|
|
+ assertTrue(iron.containsKey("参考范围下限为 0"), "参考下限 0");
|
|
|
+ assertTrue(iron.containsKey("16S 粒度"), "16S 粒度声明");
|
|
|
+ assertTrue(iron.containsKey("偏低不推荐补菌"), "不推荐补菌");
|
|
|
+ assertTrue(iron.containsKey("证据等级"), "证据等级");
|
|
|
+ assertTrue(String.valueOf(iron.get("证据等级")).contains("关联非因果"), "证据等级标注关联非因果");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void lowSidePatch_四机制_含耗氧定植抵抗维生素免疫训练() throws Exception {
|
|
|
+ UnifiedKnowledgeBaseService service = buildServiceFromSeed();
|
|
|
+ Map<String, Object> mech = castMap(service.getLowSideJudgmentPatch().get(KEY_FOUR_MECHANISMS));
|
|
|
+
|
|
|
+ assertEquals(5, mech.size(), "四机制 + 综合提示:耗氧维持厌氧/定植抵抗/维生素合成/免疫训练/综合提示");
|
|
|
+ assertTrue(mech.containsKey("耗氧维持肠腔厌氧"), "机制① 耗氧维持肠腔厌氧");
|
|
|
+ assertTrue(mech.containsKey("定植抵抗与生态位"), "机制② 定植抵抗与生态位");
|
|
|
+ assertTrue(mech.containsKey("维生素合成"), "机制③ 维生素 K2/B 合成");
|
|
|
+ assertTrue(mech.containsKey("免疫训练"), "机制④ 低剂量 LPS 免疫训练");
|
|
|
+ assertTrue(mech.containsKey("综合提示"), "综合提示(共生株/非产毒株前提)");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void lowSidePatch_报告口径_仅结构性引用且禁因果() throws Exception {
|
|
|
+ UnifiedKnowledgeBaseService service = buildServiceFromSeed();
|
|
|
+ Map<String, Object> caliber = castMap(service.getLowSideJudgmentPatch().get(KEY_REPORT_CALIBER));
|
|
|
+
|
|
|
+ assertTrue(caliber.containsKey("章节"), "报告口径含章节定位");
|
|
|
+ assertTrue(caliber.containsKey("原文口径"), "报告口径含原文口径");
|
|
|
+ String usage = String.valueOf(caliber.get("用法"));
|
|
|
+ assertTrue(usage.contains("参考下限 0") && usage.contains("99.52%"), "用法保留参考下限0与人群检出率");
|
|
|
+ assertTrue(usage.contains("个人实测"), "报告口径明确不携带个人实测值");
|
|
|
+
|
|
|
+ String redline = String.valueOf(service.getLowSideJudgmentPatch().get("引用红线"));
|
|
|
+ assertTrue(redline.contains("关联非因果"), "引用红线标关联非因果");
|
|
|
+ assertTrue(redline.contains("缺大肠杆菌→致病/需补充"), "引用红线禁缺X桥接");
|
|
|
+ assertTrue(redline.contains("禁把调整建议写成处方"), "引用红线禁止处方化表述");
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 构建 DB 降级(classpath 种子内存模式)的统一知识库服务 */
|
|
|
+ private static UnifiedKnowledgeBaseService buildServiceFromSeed() throws Exception {
|
|
|
+ UnifiedKnowledgeBaseService service = new UnifiedKnowledgeBaseService();
|
|
|
+ KnowledgeBaseSectionMapper mapper = mock(KnowledgeBaseSectionMapper.class); // 未打桩 → 空/0,走种子导入
|
|
|
+ inject(service, "knowledgeBaseSectionMapper", mapper);
|
|
|
+ inject(service, "objectMapper", new ObjectMapper());
|
|
|
+ service.load();
|
|
|
+ return service;
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private static Map<String, Object> castMap(Object o) {
|
|
|
+ assertNotNull(o, "子节内容不能为空");
|
|
|
+ return (Map<String, Object>) o;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void inject(Object target, String fieldName, Object value) throws Exception {
|
|
|
+ Class<?> type = target.getClass();
|
|
|
+ while (type != null) {
|
|
|
+ try {
|
|
|
+ Field f = type.getDeclaredField(fieldName);
|
|
|
+ f.setAccessible(true);
|
|
|
+ f.set(target, value);
|
|
|
+ return;
|
|
|
+ } catch (NoSuchFieldException e) {
|
|
|
+ type = type.getSuperclass();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new NoSuchFieldException(fieldName);
|
|
|
+ }
|
|
|
+}
|