소스 검색

test(乐收赢配置): yml 取值限定在段内 —— 汇安融的 base-url 排在前面时取错了键

ymlLine 原来在整份 application.yml 里取「第一次出现」的 `key:`,隐含依赖
「键名全文件唯一」。并入汇安融通道时这份 yml 新增了 har.base-url,而它排在
leshouying.base-url **之前** ⇒ 该函数返回 HAR 的空串,DOC_TEST_BASE_URL
那条断言报 expected: <https://test.gdyfsk.com/yfpay> but was: <"">。

键名全文件唯一不是本函数该依赖的性质:真正的危险不是报红(报红会被发现),
是将来两个段的同名键被配成同一个值时**取错键仍然报绿** —— 假绿比假红贵。
改成先截出指定顶级段再在段内取;段内唯一是可靠的,同一个段里同名键本来就是
YAML 错误。

`sectionText` 的段边界是「下一个顶级键(行首为字母/下划线)」,空行与行首注释
不算边界,所以段内穿插注释不会把段提前截断。

读数为本次改动留下:LeshouyingPropertiesTest 13 条全绿(与 HarOpenControllerTest
合并跑 24 条全绿)。本提交只动这一个测试文件,不改任何生产代码。
alphaH 3 주 전
부모
커밋
a631b9fc92
1개의 변경된 파일과 30개의 추가작업 그리고 6개의 파일을 삭제
  1. 30 6
      java/src/test/java/com/payment/platform/module/payment/leshouying/config/LeshouyingPropertiesTest.java

+ 30 - 6
java/src/test/java/com/payment/platform/module/payment/leshouying/config/LeshouyingPropertiesTest.java

@@ -246,7 +246,7 @@ class LeshouyingPropertiesTest {
                 placeholderDefault(yml, "LESHOUYING_INST_NO"),
                 "DOC_TEST_INST_NO 与 application.yml 的 ${LESHOUYING_INST_NO:...} 默认值不一致");
         assertEquals(LeshouyingProperties.DOC_TEST_BASE_URL,
-                ymlLine(yml, "base-url"),
+                ymlLine(yml, "leshouying", "base-url"),
                 "DOC_TEST_BASE_URL 与 application.yml 的 base-url 不一致");
     }
 
@@ -282,7 +282,7 @@ class LeshouyingPropertiesTest {
         for (String[] pair : keyToEnv) {
             String key = pair[0];
             String env = pair[1];
-            assertEquals("${" + env + ":}", ymlLine(yml, key),
+            assertEquals("${" + env + ":}", ymlLine(yml, "leshouying", key),
                     "leshouying." + key + " 的值必须恰好是 ${" + env
                             + ":}(键名或环境变量名漂移都会让它在运行时静默失效)");
             assertEquals("", placeholderDefault(yml, env),
@@ -297,10 +297,34 @@ class LeshouyingPropertiesTest {
         return m.group(1);
     }
 
-    /** 取 `key: value` 这种平铺配置项的值(去空白)。只匹配第一次出现。 */
-    private static String ymlLine(String yml, String key) {
-        Matcher m = Pattern.compile("(?m)^\\s*" + Pattern.quote(key) + "\\s*:\\s*(\\S+)\\s*$").matcher(yml);
-        assertTrue(m.find(), "application.yml 里找不到 " + key);
+    /**
+     * 取 application.yml **指定段内** `key: value` 这种平铺配置项的值(去空白)。
+     *
+     * ★ 为什么必须限定段(2026-09-24 实测):原实现是整文件取「第一次出现」,
+     *   隐含依赖「键名在整个文件里唯一」。并入汇安融(HAR)通道时这份 yml 新增了
+     *   `har.base-url`,而它排在 `leshouying.base-url` **之前**
+     *   ⇒ 原实现返回 HAR 的空串,`DOC_TEST_BASE_URL` 那条断言报
+     *   `expected: <https://test.gdyfsk.com/yfpay> but was: <"">`。
+     *   键名全文件唯一**不是**本函数该依赖的性质:若将来两个段的 base-url 被配成
+     *   同一个值,取错键还会**报绿**(假绿比假红贵)。段内唯一是可靠的 ——
+     *   同一个段里同名键本来就是 YAML 错误。
+     */
+    private static String ymlLine(String yml, String section, String key) {
+        String sec = sectionText(yml, section);
+        Matcher m = Pattern.compile("(?m)^\\s*" + Pattern.quote(key) + "\\s*:\\s*(\\S+)\\s*$").matcher(sec);
+        assertTrue(m.find(), "application.yml 的 " + section + " 段里找不到 " + key);
         return m.group(1);
     }
+
+    /**
+     * 截出顶级段 `section:` 的正文:从该行之后,到下一个**顶级键**(行首为字母/下划线)为止。
+     * 空行与行首 `#` 注释不算边界,故段内注释穿插不会把段提前截断。
+     */
+    private static String sectionText(String yml, String section) {
+        Matcher head = Pattern.compile("(?m)^" + Pattern.quote(section) + ":\\s*$").matcher(yml);
+        assertTrue(head.find(), "application.yml 里找不到顶级段 " + section + ":");
+        Matcher next = Pattern.compile("(?m)^[A-Za-z_]").matcher(yml);
+        int end = next.find(head.end()) ? next.start() : yml.length();
+        return yml.substring(head.end(), end);
+    }
 }