You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

6.8 KiB

Fairness 认证夹具隔离修复(A6 后独立纯测试提交)

日期:2026-09-17 分支:refactor/r01-structure-performance A6 提交:c6db74a1a8300e1aab8a452fb67909f86861fa43 本轮性质:纯测试修复 —— 生产代码 diff 为 0,Flyway 为 0,OpenAPI 为 0


0. 结论

FairnessMonitoringControllerTest 已不再依赖种子数据、测试执行顺序或共享表清空, 单独运行稳定通过;并新增反证测试锁定该隔离性。


1. 缺陷(A6 独立复验定位)

环节 事实
冲突 该测试用 token(1L, "ADMIN") / token(2L, "STUDENT"),而 V1_1__seed_data.sql 的种子账号占用 users.id = 1/2/3
被禁用 V43__disable_legacy_seed_accounts.sql 把这三行置为 is_active = 0
夹具缺陷 TestAuthTokens.writeSession() 仅在 SELECT COUNT(*) FROM users WHERE id = ? 为 0 时 INSERT,不会激活已存在的禁用行
后果 AuthSessionService.isSessionActive() 的用户检查短路 → 全部 Token 请求 401
被掩盖 全量顺序下 com.mydreamjob.controller.AuthIntegrationTest 的 @BeforeEach 执行 userRepository.deleteAll(),偶然清掉种子行,夹具随后才补建 active 用户

单跑实测(修复前):Tests run: 7, Failures: 6,全部 Status expected:<200|403|400> but was:<401>。

详见 docs/r01-a6-independent-verification-20260917.md §9。


2. 修复方案

选择:让 FairnessMonitoringControllerTest 使用独占用户,而不是修改公共 TestAuthTokens。 理由:公共 helper 若"自动激活已存在的 inactive 用户",会静默复活本应被禁用的账号 (包括生产语义上被 V43 禁用的种子账号),风险远大于收益。

2.1 改动内容

项 修复前 修复后
夹具身份 userId = 1 / 2(与种子账号冲突) 独占 ADMIN_USER_ID = 9_310_001L、STUDENT_USER_ID = 9_310_002L
手机号 由 TestAuthTokens 隐式生成 "t"+id 独占 a6fair-admin / a6fair-student
用户来源 依赖 TestAuthTokens 的"不存在才插入" @BeforeEach 显式插入 is_active = 1 的独占用户
清理 无 @AfterEach 按精确 ID、按外键顺序删除:auth_tokens → user_roles → users

@BeforeEach 先执行与 @AfterEach 相同的精确清理再插入,因此对"上轮异常中断残留"具备幂等性, 且从不把任何已存在的 inactive 用户直接激活(是删除后重建自有行)。

2.2 未使用的手段(明确排除)

未改 V43;未改生产认证逻辑;未使用 deleteAll() 清空共享表;未使用 @DirtiesContext 掩盖污染; 未捕获并忽略约束异常;未依赖测试执行顺序;未放宽任何既有 Fairness 断言;未修改公共 TestAuthTokens。


3. 反证测试 FairnessMonitoringFixtureIsolationTest(7 例)

# 用例 覆盖点
1 fixtureIdsAreOutsideSeedAccountRange 夹具 ID 不在种子号段 1/2/3;夹具用户确为 active;未占用种子手机号
2 seedRowsInactiveOrAbsent_stillAuthenticates 种子行 inactive(V43 状态) 与 完全缺失 两种前置下端点均返回 200
3 repeatedProvisioningAndRequests_doNotConflict 连续 3 轮"装配 + 请求"均成功,且不产生重复用户行
4 fixtureCycleLeavesSeedRowsUntouched 完整周期前后种子行逐字段不变(顺序无关的根本保证)
5 cleanupRemovesOnlyOwnFixtureRows 清理只删本类行;探针用户及其会话不受波及
6 unrelatedUsersAndSessionsUnchanged 非夹具用户与会话逐字段不变
7 publicTokenFixtureDoesNotSilentlyReviveInactiveUser TestAuthTokens 对已存在 inactive 用户不激活,该 Token 请求为 401 且 Service 零调用

用例 2 会临时快照并按主键原样恢复种子行(try 语义由 @AfterEach 兜底),不新增、不批量重建。


4. 验证矩阵

命令均在 mydreamjob-server/ 下执行;日志位于 docs/acceptance/r01-d4-2-20260916/ff-*.log。

# 命令 结果 日志
1 mvn -Dtest="FairnessMonitoringControllerTest" test 7 / 7,F=0 E=0 S=0 ✔ ff-1-standalone.log
2 mvn -Dtest="FairnessMonitoringFixtureIsolationTest,FairnessMonitoringControllerTest" test 14 / 14,F=0 E=0 S=0 ✔ ff-2-isolation.log
3 Fairness 先跑 ×3(-Dsurefire.runOrder=reversealphabetical) 13 / 13 ×3 ✔ ff-3-fairnessfirst-{1,2,3}.log
4 Auth 先跑 ×3(-Dsurefire.runOrder=alphabetical) 13 / 13 ×3 ✔ ff-4-authfirst-{1,2,3}.log
5 mvn clean verify 见 §4.1 ff-5-clean-verify.log
6 python ..\docs\verify_openapi.py 176 paths / 214 operations,All checks passed ✔ —

顺序说明:surefire 默认 runOrder=filesystem 会忽略 -Dtest 的书写顺序, 因此额外用 -Dsurefire.runOrder=reversealphabetical(Fairness 先)与 =alphabetical(Auth 先) 强制两个方向,并在日志中逐次核对实际执行顺序(reversealphabetical 下 scoringmonitoring.FairnessMonitoringControllerTest 确在 controller.AuthIntegrationTest 之前)。 runOrder=testorder 在本仓库使用的 surefire 3.5.6 中不可用(已实测报错)。

4.1 全量结果

项 数值
全量测试总数 2278 → 2285(+7:新增反证测试类)
Failures / Errors / Skipped 0 / 0 / 0 ✔
生产代码 diff 0 ✔
V1–V45 未改动 ✔
docs/openapi-rc.json 未修改 ✔

5. 修改文件

mydreamjob-server/src/test/java/com/mydreamjob/scoringmonitoring/FairnessMonitoringControllerTest.java      (修改:夹具独占化)
mydreamjob-server/src/test/java/com/mydreamjob/scoringmonitoring/FairnessMonitoringFixtureIsolationTest.java(新增:反证测试)
docs/r01-a6-fairness-fixture-isolation-fix-20260917.md                                                        (新增:本报告)
docs/backend-development-roadmap.md                                                                           (夹具问题关闭记录)

无生产代码、无 Flyway、无 ErrorCode、无 DTO、无接口、无 OpenAPI、无 Filter/Accessor/SecurityConfig 改动。


6. 明确声明

  • 未修改任何生产代码,未修改 V43,未修改公共 TestAuthTokens 夹具。
  • 未删除、未放宽任何既有断言;FairnessMonitoringControllerTest 的业务断言逐字保留。
  • 未使用 deleteAll()、@DirtiesContext、顺序依赖或异常吞没等掩盖手段。
  • 未与 R01-B 混合。

FairnessMonitoringControllerTest 单跑夹具缺陷已通过独立纯测试提交修复; 该测试不再依赖种子数据状态与测试执行顺序。