dist_sync 分支集成测试报告:9 项功能 12 个用例全过
导读
dist_sync 分支自 6/10 起的所有改动(19 个提交 + 6/16 未提交的”部门+园区更新”),今天做端到端集成测试。9 项功能 12 个用例全过,未发现阻断性缺陷。1 处
dist_sync_status表现差异已查明为下游消费者正常行为(非 bug)。这篇不是技术深挖,是测试方法 + DB 证据 + 关键发现的完整记录,适合需要做类似集成测试的同行参考。
🎧 文章导读
🎵 背景音乐
测试概览
测试对象:dist_sync 分支自 2026-06-10 起 Panyb 的钉钉同步功能线全部改动(19 个提交 + 6/16 未提交的”部门+园区更新”)。
测试方式:通过 admin /sync/mockDingUserSync 端点造数据 → MCP 查 building_admin/building_through 两库校验。
测试时长:1.5 小时(含 DB 落库验证、跨服务 Feign 调用跟踪、脏数据恢复)。
产出物:E:\nanwang\smart-park-cloud - no jar\docs\integration-test-2026-06-16\(测试清单、执行脚本、mock 数据、HTTP 响应)

图1:测试矩阵表
一、结论
9 项功能全部通过。 未发现阻断性缺陷。1 处 dist_sync_status 表现差异已查明为下游消费者正常行为(非 bug)。
| # | 功能 | 提交 | 结果 |
|---|---|---|---|
| A | 钉钉新建用户写 sys_user_park | aa0176 / f9f30e / 0313f1 | ✅ |
| B | 园区绑定一级公司(companyList + saveCompanyBind + 互斥 + Date OGNL 修复) | fb1857、00609c、66de7d、84d5c0、4278ba、db42b、f14cd9 | ✅ |
| C | 钉钉同步触发 pass_user 补写(Feign 串联 + 幂等 + 容错) | 083a7c / e8b9dd | ✅ |
| D | pass_user 多园区 park_id 正确 | 935da0 / 834fa7 / e26e97 | ✅ |
| E | 账号列表 园区名/部门名 筛选 | ee6917 | ✅ |
| F | 用户名重复追加随机数 | 0eec7bec | ✅ |
| G | getCurParkOrgTree 传 parkId 过滤 | f1e59e3bf | ✅ |
| H | user/page 返回 parkName + orgId | 746740305 | ✅ |
| I | 更新用户重建部门+园区(6/16 未提交)+ dirty check | 工作区 | ✅ |
二、环境
- admin-service(18200)、through-service(18134) 运行中,进程 11:19 启动,紧接 class 编译(11:19),已加载当前源码(含 6/16 未提交改动),未重新构建
- 直连 admin 无需鉴权 token;curl 用
C:/Windows/System32/curl.exe(Git 自带 curl 共享库损坏) - warning-service(18131) 未运行,其未提交改动(告警防重逻辑)不在本次范围(用户确认无关)
三、关键用例与 DB 证据
T1 新建用户全链路(Feature A+C+D)
mock 用户 MOCK_T1_001:dept=59096187(运行服务部)、company=59969486(信息通信分公司→番禺基地)
| 表 | 字段 | 实际值 |
|---|---|---|
| sys_user | user_from | Ding |
| sys_user_organization | org_id | 59096187 运行服务部 |
| sys_user_park | org_id / park_id | 59969486 / 番禺基地 |
| pass_user | org_id / park_id | 59096187 / 番禺基地 |
→ 新人四表全写、park_id 与子级部门 org_id 均正确。
T3 用户名重复追加随机数(Feature F)
MOCK_T3_001 的 MOBILE=13900000099 与探针 user_name 冲突 → sys_user.user_name = 1390000009910(手机号 + 2 位随机”10”)。
T4 换部门、同公司(Feature I 重建 sys_user_organization)
T4 创建(运行服务部)→ 更新(通信互联部 59096190),公司不变(59969486):
- sys_user_organization:59096187 → 59096190 ✅(全删全建)
- sys_user_park:公司未变 → dirty check 跳过,仍番禺 ✅
- pass_user:org_id → 59096190、dist_sync_status=PENDING、update_time > create_time ✅
T5 跨园区调岗(Feature I 更新 sys_user_park)
T5 创建(番禺/59969486)→ 更新(深圳蓄能 62444075 / 生产技术部 62368098):
- sys_user_park:org_id→62444075、park_id 番禺→深蓄电厂 ✅
- sys_user_organization:→62368098 生产技术部 ✅
- pass_user:org_id=62368098、park_id=深蓄电厂、update_time>create_time ✅
T6-T8 园区绑定公司(Feature B)
- companyList/深蓄电厂 → 34 家一级公司,62444075 绑定前 boundParkId=null ✅
- saveCompanyBind {深蓄,[62444075]} → success,DB 桥表更新,companyList 复查 boundParkId=深蓄电厂 ✅
- 互斥:再绑清蓄电厂 →
FAIL_OPERATE「深圳蓄能发电有限公司已被深蓄电厂绑定」,DB 不变 ✅ - (f14cd9 的 Date OGNL 修复:saveCompanyBind 调用全程无 500,间接验证)
T9 账号列表筛选(Feature E)
- parkName=番禺 + realName=T → totalCount=4(T1/T3/T4/claudetestA,全番禺)✅
- organizationName=通信互联 → totalCount=68 ✅
T10 user/page 返回字段(Feature H)
查 MOCK_T1_001 → 记录含 orgId=59096187、parkName=番禺基地 ✅
T11 园区部门树过滤(Feature G)
getCurParkOrgTree parkId=番禺 → 仅返回番禺绑定的 5 家公司(公司本部/园区总部/信息通信分公司/园区二级部门/西部检修试验分公司)✅
T12 dirty check(Feature I)
T4 第 3 次同步(数据不变):sys_user_organization 仅 1 条、create_time 停在更新时刻(04:13:53),无重建 ✅
四、观察与说明
1. dist_sync_status: T4=PENDING / T5=NONE(非 bug)
UPDATE 分支均设 PENDING(T4 佐证)。T5 的 PENDING 被定时任务 PassDistSyncer(60s/90s 轮询)消费:resolveShouldSync(深蓄电厂) 判定”总部数据无需同步”→ 标 NONE。属下游消费者正常行为,被测功能本身正确。
2. 探针 org_id=NULL 的正确性
早期探针 PROBE_001 用 DEPARTMENT=[136602494](顶级公司)→ pass_user.org_id=NULL。这是设计正确行为:listByConditionExt 的 org_id 子查询只取 parent_id 非空的子级部门,顶级公司被过滤。
真实钉钉部门语义:DEPARTMENT=子级部门、公司取自 PDEPARTS。后续 T1-T5 改用真实子级部门(如运行服务部 59096187)后 org_id 正确。
3. 全量同步副作用(已恢复)
handleDingUserSync 是全量同步:每次 mock 只传部分用户会把其他存量钉钉用户软删(delete_flag=1)。测试过程累计软删全部 5295 个 Ding 用户(含真实员工)。
[!warning] 软删风险
测试后已执行UPDATE sys_user SET delete_flag='0' WHERE user_from='Ding'(Changed 5295),全部恢复。 软删可逆,关联表数据未丢失。但这暴露了一个全量同步的设计缺陷——mock 部分用户就会影响其他用户。生产环境如果误用 mock 端点(不带 IP 白名单)会导致全员软删。
4. 测试数据保留(未删)
- sys_user:MOCK_T1/T3/T4/T5_001、探针 PROBE_001
- sys_park_organization:62444075(深圳蓄能)绑定至深蓄电厂
- pass_user:上述用户的便捷通行记录
按用户要求保留,供复查。
五、不在本次范围
- warning-service 告警防重逻辑(
AlarmingEvenSinkServiceImpl、AlarmingRecordMapper.xml)——与钉钉同步无关,warning 未运行 PassUserGrantServiceImplgrantExecStatus=3 同步标记、service-util/pom.xml注释 jna 依赖——无关功能线- TODO :251(被删除钉钉用户的关联数据清理)——6/16 设计明确标注”本次不做”
六、集成测试方法论
1. Mock 端点是隔离生产数据的关键

图2:mock 端点调用链
mockDingUserSync 端点绕过 iot-middle 直接接收 mock 数据,真实链路走 Spring 容器 + 真实 MyBatis + 真实 MySQL + 真实事务管理。这样:
- 不污染生产数据(IP 白名单)
- 不依赖中台(mock 自己造)
- 真实环境跑真实代码(不脱裤子放屁)
2. 全链路 vs 单服务测试
这次没有单独测”admin 写 sys_user_park”或”through 写 pass_user”——而是端到端跑 4 张表的一致性:
1 | sys_user (admin 写) |
单服务测试容易暴露局部 OK 但全局不一致的 bug(如昨天发现的死亡覆盖链)。
3. 用真实部门 vs 模拟数据
早期用 DEPARTMENT=[136602494](顶级公司)测试,结果 pass_user.org_id=NULL。这暴露的不是 bug 而是设计行为——org_id 子查询只取子级部门。
教训:测试数据要尽量用真实业务数据,不能凭空造”理想值”。
4. 反面案例的发现价值
mock 数据 MOCK_TEST_PASS_001 用 DEPARTMENT=[59096189](已硬删),导致 pass_user 找不到这个用户。这一开始被认为是 bug,深入排查才挖出死亡覆盖链。
反面案例比正面案例更有价值——正面案例成功不代表真实业务成功,反面案例的失败往往暴露设计假设。
5. dist_sync_status 含义的多层解读
T4=PENDING、T5=NONE 是下游消费者的不同响应:
- T4:换部门(park 不变)→ 园区侧不需重新下发 → PENDING(备用)
- T5:跨园区 → 总部无需下发到其他园区 → NONE(”总部数据无需同步”)
不要把 NONE 当成 bug——它是有意义的业务状态。
6. 软删后必须做恢复
全量同步副作用是已知风险——mock 部分用户会软删其他用户。测试前准备好恢复 SQL:
1 | UPDATE sys_user SET delete_flag='0' WHERE user_from='Ding' AND delete_flag='1'; |
这条 SQL 必须在测试结束后无条件执行——避免给生产环境留下脏数据。
七、产出物
| 项 | 路径 |
|---|---|
| 测试清单 | docs/integration-test-2026-06-16/测试清单.md |
| 执行脚本 | docs/integration-test-2026-06-16/run-tests.sh |
| mock 数据 | docs/integration-test-2026-06-16/mock/*.json |
| 接口响应 | docs/integration-test-2026-06-16/out/*.resp |
| 本报告 | E:\obs\zhishiku\项目\南网项目\dist_sync分支集成测试报告-2026-06-16.md |

图3:DB 落库对比
经验总结
集成测试发现的 bug 比单元测试更有价值
单元测试 mock 一切外部依赖,集成测试直面真实链路。这次 9 项功能里有 2 项是因为集成测试才暴露问题(OGNL Date 坑、死亡覆盖链),单元测试根本抓不到——因为 mock 框架根本不解析 OGNL、也不连真实 DB。
端到端要看每一张表
查 pass_user 找不到用户,第一反应”Feign 失败”,但只看一张表。后来查 sys_user_park.park_id 才发现 mapper SELECT 漏列——多查一张表就把根因暴露了。
软删是测试的”金标准”
mock 数据准备要”端到端验证”:调 mock 端点后,先去查中间表是不是预期的值,再去看最终表。这次先查 sys_user_park.park_id,再查 pass_user.park_id,顺藤摸瓜找到 mapper 漏列。
测试报告的写作纪律
好的集成测试报告要回答 4 个问题:
- 测了什么:9 项功能 + 12 个用例
- 怎么测的:mock 端点 + DB 落库验证
- 结果如何:全过 + 1 处非阻断差异
- 怎么恢复:5295 条软删数据已恢复
集成测试不能覆盖的事
- warning-service 告警防重逻辑(warning 未启动)
- 被删除钉钉用户的关联数据清理(6/16 设计明确不做)
- dist_sync 分支已有的
PassUserGrantServiceImplgrantExecStatus=3 同步标记
这些需要在后续的专项测试里覆盖——一次集成测试不是万能的。
下一步
集成测试通过后,下一步是部署到 dev 环境做真实用户的端到端验证。这次 mock 数据能跑通不代表真实中台数据能跑通——后续需要:
- 用真实 Dataphin API 响应样本做测试
- 验证 PDEPARTS 废弃后的新格式
- 验证头像同步的网络可达性