test-design.md 89 KB

权限管理系统 (perms-system-server) — 全路径覆盖测试设计

测试范围: API (go-zero REST, 全 POST) + gRPC (status codes) + Model 层 (_gen.go 模板生成 + 自定义方法) + Logic 单元测试 + util 层 + 访问控制 + UserDetailsLoader 测试报告与代码审计详见 test-report.md


一、系统架构与逻辑链路

1.1 整体调用链路

HTTP Client                                  gRPC Client
     │                                            │
     ▼                                            ▼
rest.Server (go-zero)                    zrpc.Server (go-zero)
     │ (全部 POST 路由)                            │
     ▼                                            ▼
Handler 层 (JSON Body 解析)              PermServer (permserver.go)
     │                                   (status.Error + codes.Xxx)
     ▼                                            │
JwtAuth Middleware (鉴权/上下文注入)                │
     │                                            │
     ▼                                            ▼
Logic 层 (业务逻辑)  ◄────── 共享 ────►  authHelper (jwt.go / perms.go)
     │                                            │
     ▼                                            ▼
util 层 (NormalizePage / IsValidEmail / IsValidPhone)
     │
     ▼
Model 层 (go-zero sqlc + cache + TransactCtx + 批量查询)
     │  ├── _gen.go (自定义模板生成: CRUD/Batch/WithTx/缓存管理)
     │  └── 自定义方法 (分页/按条件查询/级联删除等)
     ▼
MySQL (InnoDB) + Redis Cache

1.2 Model 层接口全景

共 9 个 Model,每个包含:

层级 方法类别 数量/模型 来源
_gen.go 基础 CRUD Insert, InsertWithTx, FindOne, FindOneWithTx, Update, UpdateWithTx, Delete, DeleteWithTx 8 自定义模板
_gen.go 批量操作 BatchInsert, BatchInsertWithTx, BatchUpdate, BatchUpdateWithTx, BatchDelete, BatchDeleteWithTx 6 自定义模板
_gen.go 唯一索引查询 FindOneBy{UniqueField}, FindOneBy{UniqueField}WithTx (因表而异) 0~2 组 自定义模板
_gen.go 内部辅助 TransactCtx, TableName, findListByPrimaryKeys, getPrimaryKeyValue, buildBatchUpdateQuery, formatPrimary, queryPrimary 7 自定义模板
自定义方法 分页查询/按条件查询/级联删除/批量ID查询等 3~7 手写

1.3 权限计算逻辑链路

输入: userId + deptId + productCode + isSuperAdmin(bool)
    │
    ├─ isSuperAdmin=true → 产品全部启用权限 + "SUPER_ADMIN"
    ├─ 非产品成员 → nil + ""
    ├─ DEVELOPER/ADMIN → 产品全部启用权限 + memberType
    ├─ MEMBER + deptId>0 + dept.DeptType="DEV" → 产品全部启用权限 + "MEMBER"
    ├─ MEMBER + deptId>0 + dept查询失败/DeptType≠"DEV" → 继续走角色权限流程
    └─ MEMBER → (角色权限 ∪ ALLOW) - DENY → 过滤 status=1

二、REST API 测试用例

注意: 所有路由统一为 POST 方法,请求参数均通过 JSON Body 传递。

2.1 产品端登录 POST /api/auth/login

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0001 POST /api/auth/login 正常登录(普通用户+productCode) {"username":"user1","password":"123456","productCode":"test"} code=0, accessToken/refreshToken/userInfo 正常路径 P0 loginLogic全路径
TC-0002 POST /api/auth/login 正常登录-带productCode+ADMIN成员 {"username":"user1","password":"123456","productCode":"test"} code=0, perms含用户可用权限, memberType="ADMIN" 正常路径 P0 GetUserPerms(false) MEMBER分支
TC-0003 POST /api/auth/login 超管通过产品端登录被拒绝 {"username":"super","password":"x","productCode":"p1"} code=403, "超级管理员不允许通过产品端登录,请使用管理后台" 安全 P0 IsSuperAdmin==1 → ErrForbidden
TC-0004 POST /api/auth/login 超管无productCode被拒绝 {"username":"super","password":"x"} code=403, "超级管理员不允许通过产品端登录,请使用管理后台" 安全 P0 IsSuperAdmin==1 → ErrForbidden
TC-0005 POST /api/auth/login 用户不存在 {"username":"notexist","password":"x"} code=401, "用户名或密码错误" 异常路径 P0 ErrNotFound分支
TC-0006 POST /api/auth/login DB异常(非ErrNotFound) FindOneByUsername连接失败 code=500, "服务器内部错误" 异常路径 P1 透传err→Setup兜底
TC-0007 POST /api/auth/login 密码错误 {"username":"admin","password":"wrong"} code=401 异常路径 P0 bcrypt比对失败
TC-0008 POST /api/auth/login 账号冻结 status=2用户 code=403, "账号已被冻结" 分支覆盖 P0 u.Status!=1
TC-0009 POST /api/auth/login 非产品成员 productCode指向用户不属于的产品 code=403, "您不是该产品的成员" 安全 P0 非成员禁止登录
TC-0010 POST /api/auth/login DEVELOPER成员 DEVELOPER类型成员 perms全量, memberType="DEVELOPER" 分支覆盖 P1 perms.go DEVELOPER分支
TC-0011 POST /api/auth/login SQL注入 {"username":"' OR 1=1 --","password":"x"} code=401 安全 P0 参数化查询
TC-0012 POST /api/auth/login 缺少必填字段 {} HTTP 400 边界 P1 httpx.Parse校验(productCode现为必填)
TC-0013 POST /api/auth/login 产品成员被禁用时拒绝登录 member.status=Disabled 403 "您的产品成员资格已被禁用" 安全 P0 H-3: loginService
TC-0014 POST /api/auth/login 产品被禁用时拒绝登录 product.status=Disabled 403 "该产品已被禁用" 安全 P0 H-3: loginService

2.1b 管理后台登录 POST /api/auth/adminLogin

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0015 POST /api/auth/adminLogin 超管正常登录 {"username":"super","password":"x","managementKey":"valid"} code=0, accessToken/refreshToken/userInfo, isSuperAdmin=1, memberType="SUPER_ADMIN", perms为空 正常路径 P0 adminLoginLogic全路径
TC-0016 POST /api/auth/adminLogin 普通用户被拒绝 {"username":"user1","password":"x","managementKey":"valid"} code=403, "仅超级管理员可通过管理后台登录" 安全 P0 审计H1修复: 仅超管可登录管理后台
TC-0017 POST /api/auth/adminLogin managementKey无效 {"username":"user1","password":"x","managementKey":"wrong"} code=401, "managementKey无效" 安全 P0 第一个校验点
TC-0018 POST /api/auth/adminLogin managementKey为空 {"username":"user1","password":"x","managementKey":""} code=401, "managementKey无效" 安全 P0 空字符串≠config值
TC-0019 POST /api/auth/adminLogin 用户不存在 {"username":"notexist","password":"x","managementKey":"valid"} code=401, "用户名或密码错误" 异常路径 P0 ErrNotFound分支
TC-0020 POST /api/auth/adminLogin 密码错误 {"username":"user1","password":"wrong","managementKey":"valid"} code=401, "用户名或密码错误" 异常路径 P0 bcrypt比对失败
TC-0021 POST /api/auth/adminLogin 账号冻结 status=2用户 code=403, "账号已被冻结" 分支覆盖 P0 u.Status!=1
TC-0022 POST /api/auth/adminLogin 不带productCode时perms为空 管理后台登录超管 userInfo.perms为空, memberType="SUPER_ADMIN"(超管标记由Loader自动填充) 功能验证 P0 Load(ctx, uid, "")
TC-0023 POST /api/auth/adminLogin 缺少必填字段 {} HTTP 400 边界 P1 httpx.Parse校验
TC-0024 POST /api/auth/adminLogin SQL注入username {"username":"' OR 1=1 --","password":"x","managementKey":"valid"} code=401 安全 P0 参数化查询

2.2 刷新Token POST /api/auth/refreshToken

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0025 POST /api/auth/refreshToken 正常刷新 Header Authorization: Bearer <refreshToken> code=0, 新accessToken, 新refreshToken(token轮转,保留原始过期时间) 正常路径 P0 refreshTokenLogic全路径
TC-0026 POST /api/auth/refreshToken 不带productCode(回退) Header Authorization, 无productCode 使用claims.ProductCode 分支覆盖 P1 productCode=""回退
TC-0027 POST /api/auth/refreshToken token无效 Header Authorization: Bearer invalid code=401 异常路径 P0 ParseRefreshToken失败
TC-0028 POST /api/auth/refreshToken 用户已删除 token中userId不存在 code=403, "账号已被冻结" 异常路径 P1 UserDetailsLoader返回Status=0
TC-0029 POST /api/auth/refreshToken 账号冻结 冻结用户 code=403 分支覆盖 P0 Status!=1
TC-0030 POST /api/auth/refreshToken 超管+productCode(token中已含相同pc) isSuperAdmin=1, token中productCode=pc, req.ProductCode=pc refreshToken原样返回, SUPER_ADMIN权限 分支覆盖 P1 isSuperAdmin分支+productCode不变
TC-0031 POST /api/auth/refreshToken 尝试切换产品被拒绝 token中productCode="p1", req.ProductCode="p2" code=400, "刷新令牌不允许切换产品" 安全 P0 H-02修复: 禁止跨产品切换

2.3 同步权限 POST /api/perm/sync

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0032 POST /api/perm/sync 全部新增 {"appKey":"ak","appSecret":"as","perms":[{"code":"x","name":"y"}]} code=0, added=1, updated=0, disabled=0 正常路径 P0 toInsert→BatchInsert
TC-0033 POST /api/perm/sync 更新已有(名称变更) 已存在code但name不同 updated=1 正常路径 P0 toUpdate→BatchUpdate
TC-0034 POST /api/perm/sync 无变化 已存在且name/remark/status均相同 added=0, updated=0 分支覆盖 P1 跳过更新
TC-0035 POST /api/perm/sync 禁用权限重启 已status=2的权限在列表中 updated=1, status恢复1 分支覆盖 P1 Status!=1条件
TC-0036 POST /api/perm/sync 移除不在列表的权限 DB有多余权限 disabled>0 正常路径 P0 DisableNotInCodes
TC-0037 POST /api/perm/sync 空perms数组被拒绝 {"...","perms":[]} code=400, "权限列表不能为空" 输入校验 P0 空列表校验,防止意外批量禁用
TC-0038 POST /api/perm/sync 验证disabled返回值 已知DB有5条,perms仅含2条 disabled=3 功能验证 P0 RowsAffected()
TC-0039 POST /api/perm/sync appKey无效 {"appKey":"invalid"} code=401 异常路径 P0 FindOneByAppKey失败
TC-0040 POST /api/perm/sync appSecret错误 secret不匹配 code=401 异常路径 P0 AppSecret比对
TC-0041 POST /api/perm/sync 产品已禁用 product.Status!=1 code=403 分支覆盖 P0 Status!=1
TC-0042 POST /api/perm/sync 大批量(1000条) 1000条perms added=1000 性能 P2 BatchInsert性能
TC-0043 POST /api/perm/sync 重复code去重 perms中包含两个相同code 仅处理一次, added=1(而非2) 分支覆盖 P0 M-09修复: seen去重
TC-0044 POST /api/perm/sync 事务保护-中途失败回滚 模拟BatchUpdate失败 全部操作回滚, 返回SyncPermsError(500,"同步权限事务失败") 事务验证 P0 H-05修复: TransactCtx, 错误包装不透传DB错误

2.4 获取用户信息 POST /api/auth/userInfo

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0045 POST /api/auth/userInfo 正常获取-含productCode Bearer token (含productCode) code=0, 完整UserInfo+实时perms 正常路径 P0 userInfoLogic全路径
TC-0046 POST /api/auth/userInfo 不含productCode Bearer token (无productCode) perms为空 分支覆盖 P1 productCode=""
TC-0047 POST /api/auth/userInfo 未登录 无Authorization头 code=401, "未登录" 异常路径 P0 middleware拦截
TC-0048 POST /api/auth/userInfo token过期 过期token code=401 异常路径 P0 middleware
TC-0049 POST /api/auth/userInfo userId=0 伪造claims code=401, "未登录" 分支覆盖 P1 userId==0

2.5 修改密码 POST /api/auth/changePassword

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0050 POST /api/auth/changePassword 正常修改 {"oldPassword":"123456","newPassword":"654321"} code=0 正常路径 P0 changePasswordLogic全路径
TC-0051 POST /api/auth/changePassword mustChangePassword重置 正常修改后 DB中mustChangePassword=2 功能验证 P0 user.MustChangePassword=2
TC-0052 POST /api/auth/changePassword 原密码错误 {"oldPassword":"wrong","newPassword":"newpwd"} code=400, "原密码错误" 异常路径 P0 bcrypt失败
TC-0053 POST /api/auth/changePassword 新密码少于6字符 {"oldPassword":"old","newPassword":"12345"} code=400, "密码长度不能少于6个字符" 输入校验 P0 len<6
TC-0054 POST /api/auth/changePassword 新密码恰好6字符 {"oldPassword":"old","newPassword":"123456"} code=0 边界 P1 len==6
TC-0055 POST /api/auth/changePassword 新密码空字符串 {"oldPassword":"old","newPassword":""} code=400 边界 P0 len("")=0<6
TC-0056 POST /api/auth/changePassword 新密码超过72字符 {"oldPassword":"old","newPassword":"a*73"} code=400, "密码长度不能超过72个字符" 输入校验 P0 len>72
TC-0057 POST /api/auth/changePassword 新密码恰好72字符 {"oldPassword":"old","newPassword":"a*72"} code=0 边界 P1 len==72
TC-0058 POST /api/auth/changePassword 新旧密码相同 {"oldPassword":"123456","newPassword":"123456"} code=400, "新密码不能与原密码相同" 输入校验 P0 OldPassword==NewPassword
TC-0059 POST /api/auth/changePassword 用户不存在 token中userId已删除 code=404 异常路径 P1 FindOne失败

2.6 创建产品 POST /api/product/create

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0060 POST /api/product/create 正常创建 {"code":"new","name":"新产品"} code=0, id/appKey/appSecret/adminUser/adminPassword 正常路径 P0 TransactCtx全路径
TC-0061 POST /api/product/create 事务回滚-用户创建失败 模拟InsertWithTx User失败 返回错误, DB无新产品 事务验证 P0 TransactCtx回滚
TC-0062 POST /api/product/create 事务回滚-成员创建失败 模拟InsertWithTx Member失败 产品和用户均回滚 事务验证 P0 TransactCtx回滚
TC-0063 POST /api/product/create 编码已存在 {"code":"existing","name":"x"} code=409 异常路径 P0 FindOneByCode成功
TC-0064 POST /api/product/create 并发创建同编码 两请求同时 一成功一冲突 并发 P1 uk_code

2.7 产品更新/列表/详情

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0065 POST /api/product/update 正常更新 {"id":1,"name":"新名","status":1} code=0 正常路径 P0 updateProductLogic
TC-0066 POST /api/product/update 不存在 {"id":9999,"name":"x"} code=404 异常路径 P0 FindOne失败
TC-0067 POST /api/product/update 不传status {"id":1,"name":"x"} status不变 分支覆盖 P1 Status>0
TC-0068 POST /api/product/list 正常分页 {"page":1,"pageSize":10} code=0, total/list 正常路径 P0 productListLogic
TC-0069 POST /api/product/list 默认分页 {} page=1, pageSize=20 分支覆盖 P1 NormalizePage默认值
TC-0070 POST /api/product/list pageSize超过上限 {"page":1,"pageSize":500} 实际pageSize=100 边界 P0 NormalizePage cap 100
TC-0071 POST /api/product/list pageSize=0 {"page":1,"pageSize":0} 实际pageSize=20 边界 P1 NormalizePage<=0→20
TC-0072 POST /api/product/list page负值 {"page":-1,"pageSize":10} 实际page=1 边界 P1 NormalizePage<=0→1
TC-0073 POST /api/product/detail 正常查询 {"id":1} code=0, ProductItem 正常路径 P0 productDetailLogic
TC-0074 POST /api/product/detail 不存在 {"id":9999} code=404 异常路径 P0 FindOne失败
TC-0075 POST /api/product/list 非超管AppKey隐藏 ctx=MEMBER code=0, 列表中AppKey为空 安全 P0 H-11修复: AppKey仅超管可见
TC-0076 POST /api/product/list 超管可见AppKey ctx=SuperAdmin code=0, 列表中AppKey不为空 安全 P0 H-11修复: 超管可见AppKey
TC-0077 POST /api/product/detail 非超管AppKey隐藏 ctx=MEMBER code=0, AppKey为空 安全 P0 H-11修复: AppKey仅超管可见
TC-0078 POST /api/product/detail 超管可见AppKey ctx=SuperAdmin code=0, AppKey不为空 安全 P0 H-11修复: 超管可见AppKey

2.8 创建部门 POST /api/dept/create

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0079 POST /api/dept/create 创建顶级部门 {"parentId":0,"name":"总部"} code=0, path="/{id}/" 正常路径 P0 TransactCtx, parentPath="/"
TC-0080 POST /api/dept/create 创建子部门 {"parentId":1,"name":"技术部"} code=0, path=parent.path+id+"/" 正常路径 P0 parentId>0分支
TC-0081 POST /api/dept/create 父部门不存在 {"parentId":9999,"name":"x"} code=404, "父部门不存在" 异常路径 P0 FindOneWithTx失败
TC-0082 POST /api/dept/create 不传DeptType默认NORMAL {"parentId":0,"name":"x"} DB deptType="NORMAL" 分支覆盖 P0 deptType=""→DeptTypeNormal
TC-0083 POST /api/dept/create 传DeptType=DEV {"parentId":0,"name":"x","deptType":"DEV"} DB deptType="DEV" 正常路径 P0 req.DeptType赋值
TC-0084 POST /api/dept/create 事务内FindOneWithTx可见性 TransactCtx内InsertWithTx后FindOneWithTx 事务内可读到未提交数据 事务验证 P0 FindOneWithTx(session)
TC-0085 POST /api/dept/create 事务回滚-Insert失败 模拟InsertWithTx失败 DB无新记录 事务验证 P0 TransactCtx回滚
TC-0086 POST /api/dept/create 事务回滚-UpdateWithTx失败 模拟UpdateWithTx失败 Insert也回滚 事务验证 P1 TransactCtx回滚
TC-0087 POST /api/dept/create 多层嵌套(5层) 递归创建5层 path正确拼接 深度测试 P2 path逻辑
TC-0088 POST /api/dept/create 通过Logic创建+验证Path CreateDeptLogic.CreateDept→FindOne path包含/{id}/ 集成验证 P0 FindOneWithTx修复后端到端

2.9 部门更新/删除/树

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0089 POST /api/dept/update 正常更新 {"id":1,"name":"新名","sort":5} code=0 正常路径 P0 updateDeptLogic
TC-0090 POST /api/dept/update 不存在 {"id":9999,"name":"x"} code=404 异常路径 P0 FindOne失败
TC-0091 POST /api/dept/update DeptType NORMAL→DEV {"id":1,"deptType":"DEV"} DB deptType="DEV" 正常路径 P0 DeptType合法值更新
TC-0092 POST /api/dept/update DeptType无效值返回错误 {"id":1,"deptType":"INVALID"} code=400, "部门类型无效", DB deptType不变 输入校验 P0 DeptType校验,仅NORMAL/DEV
TC-0093 POST /api/dept/update DeptType变更时级联清除子部门用户缓存 部门从NORMAL改为DEV,有子部门含用户 code=0, 子部门下用户缓存被清除 缓存验证 P0 M-10修复: 级联缓存失效
TC-0094 POST /api/dept/delete 正常删除(无子部门) {"id":5} code=0 正常路径 P0 deleteDeptLogic
TC-0095 POST /api/dept/delete 有子部门 {"id":1} code=400, "存在子部门" 业务约束 P0 len(children)>0
TC-0096 POST /api/dept/delete 不存在的部门 {"id":9999} code=0(Delete对不存在行不报错) 边界 P1 FindByParentId空+Delete
TC-0097 POST /api/dept/delete 部门下有关联用户 部门id指向含用户的部门 code=400, "该部门下仍有关联用户,无法删除" 业务约束 P0 H-07修复: 检查关联用户
TC-0098 POST /api/dept/tree 正常获取 {} code=0, 树形结构, 含DeptType字段 正常路径 P0 deptTreeLogic, DeptType映射
TC-0099 POST /api/dept/tree 空数据 无数据 code=0, data=[] 边界 P1 空列表
TC-0100 POST /api/dept/tree 孤儿节点 parentId指向不存在 升级为根节点 分支覆盖 P2 parent不存在

2.10 权限列表 POST /api/perm/list

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0101 POST /api/perm/list 正常查询 {"productCode":"p1","page":1,"pageSize":10} code=0, total/list 正常路径 P0 permListLogic
TC-0102 POST /api/perm/list 默认分页 {"productCode":"p1"} page=1, pageSize=20 分支覆盖 P1 NormalizePage
TC-0103 POST /api/perm/list pageSize超过上限 {"productCode":"p1","pageSize":200} 实际pageSize=100 边界 P0 NormalizePage cap
TC-0104 POST /api/perm/list 不存在的productCode {"productCode":"notexist"} total=0, list=[] 边界 P1 空结果

2.11 角色管理

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0105 POST /api/role/create 正常创建 {"productCode":"p1","name":"管理员","permsLevel":1} code=0, id>0 正常路径 P0 createRoleLogic
TC-0106 POST /api/role/create 重复角色名 同产品同名 code=409, "该产品下角色名已存在" 业务约束 P0 Duplicate entry→ErrConflict
TC-0107 POST /api/role/create 并发同名创建 两请求同时 一成功一冲突409 并发 P1 唯一索引+1062捕获
TC-0108 POST /api/role/update 正常更新 {"id":1,"name":"新名","permsLevel":2} code=0 正常路径 P0 updateRoleLogic
TC-0109 POST /api/role/update 不存在 {"id":9999,...} code=404 异常路径 P0 FindOne失败
TC-0110 POST /api/role/list 正常查询 {"productCode":"p1","page":1,"pageSize":10} code=0 正常路径 P0 roleListLogic
TC-0111 POST /api/role/list pageSize超过上限 {"productCode":"p1","pageSize":200} 实际pageSize=100 边界 P0 NormalizePage cap
TC-0112 POST /api/role/detail 正常查询 {"id":1} code=0, 含permIds 正常路径 P0 roleDetailLogic
TC-0113 POST /api/role/detail 不存在 {"id":9999} code=404 异常路径 P0 FindOne失败

2.12 删除角色 POST /api/role/delete

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0114 POST /api/role/delete 正常删除+级联 {"id":5} (含权限/用户绑定) code=0, role_perm/user_role同步清理 正常+事务 P0 TransactCtx全路径
TC-0115 POST /api/role/delete 事务回滚 模拟DeleteWithTx失败 级联删除回滚 事务验证 P0 TransactCtx
TC-0116 POST /api/role/delete 无关联数据 新角色无绑定 code=0 分支覆盖 P1 删0条

2.13 绑定角色权限 POST /api/role/bindPerms

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0117 POST /api/role/bindPerms 正常绑定 {"roleId":1,"permIds":[1,2,3]} code=0 正常路径 P0 TransactCtx
TC-0118 POST /api/role/bindPerms 角色不存在 {"roleId":9999,"permIds":[1]} code=404, "角色不存在" 存在性校验 P0 FindOne预检
TC-0119 POST /api/role/bindPerms 清空权限 {"roleId":1,"permIds":[]} code=0, 全清空 分支覆盖 P1 len==0→return
TC-0120 POST /api/role/bindPerms 重复permId {"roleId":1,"permIds":[1,1]} DB唯一索引→事务回滚 边界 P1 uk_role_perm
TC-0121 POST /api/role/bindPerms 事务回滚 模拟BatchInsertWithTx失败 旧数据回滚还原 事务验证 P0 TransactCtx

2.14 创建用户 POST /api/user/create

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0122 POST /api/user/create 正常创建 {"username":"new","password":"123456"} code=0, id>0 正常路径 P0 createUserLogic
TC-0123 POST /api/user/create 用户名已存在(预检) {"username":"existing","password":"x"} code=409, "用户名已存在" 异常路径 P0 FindOneByUsername成功
TC-0124 POST /api/user/create 带完整可选字段 含nickname/email/phone/remark/deptId code=0 正常路径 P1 各字段赋值
TC-0125 POST /api/user/create 非法email格式 {"...","email":"not-an-email"} code=400, "邮箱格式不正确" 输入校验 P0 util.IsValidEmail
TC-0126 POST /api/user/create 合法email {"...","email":"[email protected]"} code=0 正常路径 P1 IsValidEmail通过
TC-0127 POST /api/user/create email为空(可选) {"...","email":""} code=0, 跳过校验 分支覆盖 P1 email!=""判断
TC-0128 POST /api/user/create 非法phone格式 {"...","phone":"abc"} code=400, "手机号格式不正确" 输入校验 P0 util.IsValidPhone
TC-0129 POST /api/user/create 合法phone(国际) {"...","phone":"+8613800138000"} code=0 正常路径 P1 IsValidPhone通过
TC-0130 POST /api/user/create phone为空(可选) {"...","phone":""} code=0, 跳过校验 分支覆盖 P1 phone!=""判断
TC-0131 POST /api/user/create 并发同username(TOCTOU) 两请求同时 一成功一冲突(1062) 并发 P0 Duplicate entry→ErrConflict
TC-0132 POST /api/user/create 唯一索引冲突消息 预检通过后DB冲突 code=409, "用户名已存在" 异常路径 P0 strings.Contains "1062"
TC-0133 POST /api/user/create 密码少于6字符 {"username":"x","password":"12345"} code=400, "密码长度不能少于6个字符" 输入校验 P0 H-10修复: 密码强度校验
TC-0134 POST /api/user/create 密码超过72字符 {"username":"x","password":"a*73"} code=400, "密码长度不能超过72个字符" 输入校验 P0 H-10修复: 密码强度校验

2.15 用户更新 POST /api/user/update (指针类型+DeptId可清零)

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0135 POST /api/user/update 正常更新 {"id":1,"nickname":"n","email":"[email protected]"} code=0 正常路径 P0 updateUserLogic
TC-0136 POST /api/user/update 不存在 {"id":9999} code=404 异常路径 P0 FindOne失败
TC-0137 POST /api/user/update 仅传id {"id":1} 仅updateTime变 分支覆盖 P1 所有指针nil
TC-0138 POST /api/user/update 清空nickname {"id":1,"nickname":""} DB nickname→空字符串 功能 P0 *string非nil+空值
TC-0139 POST /api/user/update 清空email {"id":1,"email":""} DB email→空字符串(跳过校验) 功能 P0 *email!=""判断
TC-0140 POST /api/user/update 清空remark {"id":1,"remark":""} DB remark清空 功能 P1 *string→""
TC-0141 POST /api/user/update 非法email格式 {"id":1,"email":"bad-email"} code=400, "邮箱格式不正确" 输入校验 P0 util.IsValidEmail
TC-0142 POST /api/user/update 非法phone格式 {"id":1,"phone":"12345"} code=400, "手机号格式不正确" 输入校验 P0 util.IsValidPhone
TC-0143 POST /api/user/update 合法phone {"id":1,"phone":"+8613800138000"} code=0 正常路径 P1 IsValidPhone通过
TC-0144 POST /api/user/update 不传email(nil) {"id":1,"nickname":"x"} email不变 分支覆盖 P1 req.Email==nil
TC-0145 POST /api/user/update DeptId设为0(取消部门) {"id":1,"deptId":0} DB deptId→0 功能 P0 *int64, *req.DeptId=0
TC-0146 POST /api/user/update DeptId设为正值 {"id":1,"deptId":5} DB deptId→5 正常路径 P0 *int64指针
TC-0147 POST /api/user/update DeptId不传(nil) {"id":1,"nickname":"x"} deptId不变 分支覆盖 P1 req.DeptId==nil
TC-0148 POST /api/user/update 超管不能冻结另一超管 caller=超管A, target=超管B, status=2 403 "不能通过此接口修改超级管理员的状态" 安全 P0 H-2: IsSuperAdmin==Yes 保护

2.16 用户列表/详情/状态 及其他用户操作

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0149 POST /api/user/list 含productCode {"productCode":"p1","page":1,"pageSize":10} 每用户含memberType(批量查) 正常路径 P0 FindMapByProductCodeUserIds
TC-0150 POST /api/user/list 不含productCode {"page":1} memberType全空,不调批量查 分支覆盖 P1 productCode=""
TC-0151 POST /api/user/list pageSize超过上限 {"pageSize":500} 实际pageSize=100 边界 P0 NormalizePage cap
TC-0152 POST /api/user/list 用户不在产品中 productCode指定,部分用户不是成员 memberType为空 分支覆盖 P1 memberMap无对应key
TC-0153 POST /api/user/list 批量查询DB异常 FindMapByProductCodeUserIds失败 code=500 异常路径 P1 err→透传
TC-0154 POST /api/user/detail 正常查询 {"id":1} 含roleIds 正常路径 P0 userDetailLogic
TC-0155 POST /api/user/detail 正常查询-含Avatar 有Avatar用户 avatar字段非空 分支覆盖 P1 Avatar.Valid=true
TC-0156 POST /api/user/detail 不存在 {"id":9999} code=404 异常路径 P0 FindOne失败
TC-0157 POST /api/user/bindRoles 正常绑定 {"userId":1,"roleIds":[1,2]} code=0 正常路径 P0 TransactCtx
TC-0158 POST /api/user/bindRoles 用户不存在 {"userId":9999,"roleIds":[1]} code=404, "用户不存在" 存在性校验 P0 FindOne预检
TC-0159 POST /api/user/bindRoles 清空角色 {"userId":1,"roleIds":[]} code=0 分支覆盖 P1 len==0
TC-0160 POST /api/user/bindRoles 事务回滚 模拟失败 旧数据还原 事务验证 P0 TransactCtx
TC-0161 POST /api/user/bindRoles 角色不属于当前产品 roleId属于其他产品 code=400, "角色不属于当前产品" 安全 P0 H-03修复: 校验角色归属
TC-0162 POST /api/user/bindRoles 角色已禁用 roleId状态为禁用 code=400, "角色已禁用" 安全 P0 H-03修复: 校验角色状态
TC-0163 POST /api/user/bindRoles 角色不存在 roleId不存在 code=400, "角色不存在" 安全 P0 H-03修复: 校验角色存在
TC-0164 POST /api/user/bindRoles 非产品成员绑定角色被拒绝 目标用户非当前产品成员 400 "不是当前产品的成员" 安全 P0 L-4: BindRoles
TC-0165 POST /api/user/setPerms 正常ALLOW {"userId":1,"perms":[{"permId":1,"effect":"ALLOW"}]} code=0 正常路径 P0 TransactCtx
TC-0166 POST /api/user/setPerms 用户不存在 {"userId":9999,"perms":[...]} code=404, "用户不存在" 存在性校验 P0 FindOne预检
TC-0167 POST /api/user/setPerms DENY权限 effect="DENY" code=0 正常路径 P0 effect="DENY"
TC-0168 POST /api/user/setPerms 清空权限 {"userId":1,"perms":[]} code=0 分支覆盖 P1 len==0
TC-0169 POST /api/user/setPerms 无效Effect值 effect="INVALID" code=400, "无效的权限效果" 安全 P0 H-04修复: Effect白名单
TC-0170 POST /api/user/setPerms PermId不存在 permId=99999 code=400, "权限不存在" 安全 P0 H-04修复: 校验PermId
TC-0171 POST /api/user/setPerms 权限不属于当前产品 permId属于其他产品 code=400, "权限不属于当前产品" 安全 P0 H-04修复: 校验权限归属
TC-0172 POST /api/user/setPerms 非产品成员设置权限被拒绝 目标用户非当前产品成员 400 "不是当前产品的成员" 安全 P0 L-5: SetUserPerms
TC-0173 POST /api/user/updateStatus 正常冻结 {"id":普通用户,"status":2} code=0 正常路径 P0 updateUserStatusLogic
TC-0174 POST /api/user/updateStatus 正常解冻 {"id":普通用户,"status":1} code=0 正常路径 P0 status=1
TC-0175 POST /api/user/updateStatus 非法status(0) {"id":1,"status":0} code=400, "状态值无效" 输入校验 P0 status!=1&&!=2
TC-0176 POST /api/user/updateStatus 冻结自己 id=当前登录userId code=400, "不能修改自己的状态" 自我保护 P0 callerId==req.Id
TC-0177 POST /api/user/updateStatus 冻结超管 id=超管 code=403, "不能修改超级管理员的状态" 超管保护 P0 IsSuperAdmin==1

2.17 成员管理

TC编号 接口/方法 测试场景 输入参数 (JSON) 预期结果 测试类型 优先级 覆盖说明
TC-0178 POST /api/member/add 正常添加 {"productCode":"p1","userId":1,"memberType":"MEMBER"} code=0, id>0 正常路径 P0 addMemberLogic
TC-0179 POST /api/member/add 产品不存在 {"productCode":"notexist",...} code=404, "产品不存在" 存在性校验 P0 FindOneByCode预检
TC-0180 POST /api/member/add 用户不存在 {"userId":9999,...} code=404, "用户不存在" 存在性校验 P0 FindOne预检
TC-0181 POST /api/member/add 已是成员 重复添加 code=409, "已是成员" 异常路径 P0 FindOneByProductCodeUserId成功
TC-0182 POST /api/member/add 并发添加 两请求同时 一成功一冲突 并发 P1 uk_product_user
TC-0183 POST /api/member/add 无效MemberType {"memberType":"INVALID"} code=400, "无效的成员类型" 输入校验 P0 M-06修复: MemberType白名单
TC-0184 POST /api/member/update 正常更新 {"id":1,"memberType":"ADMIN"} code=0 正常路径 P0 updateMemberLogic
TC-0185 POST /api/member/update 不存在 {"id":9999,...} code=404 异常路径 P0 FindOne失败
TC-0186 POST /api/member/update 无效MemberType {"id":1,"memberType":"INVALID"} code=400, "无效的成员类型" 输入校验 P0 M-06修复: MemberType白名单
TC-0187 POST /api/member/list 正常查询(批量查用户) {"productCode":"p1","page":1,"pageSize":10} 含username/nickname 正常路径 P0 FindByIds批量
TC-0188 POST /api/member/list 成员用户已删除 userId不存在于FindByIds结果 username/nickname为空 分支覆盖 P1 userMap无对应key
TC-0189 POST /api/member/list pageSize超过上限 {"productCode":"p1","pageSize":200} 实际pageSize=100 边界 P0 NormalizePage cap
TC-0190 POST /api/member/list 空成员列表 productCode下无成员 total=0, list=[], 不调FindByIds 分支覆盖 P1 userIds空
TC-0191 POST /api/member/remove 正常移除+级联(事务内) {"id":1} (含角色/权限) code=0, user_role+user_perm同步清理 正常+事务 P0 TransactCtx全路径
TC-0192 POST /api/member/remove 跨产品隔离 用户在多产品有角色 仅清理该产品的 深度业务 P0 ForProductTx子查询
TC-0193 POST /api/member/remove 成员不存在 {"id":9999} code=404, "成员不存在" 异常路径 P0 FindOne失败
TC-0194 POST /api/member/remove 事务回滚 模拟DeleteWithTx失败 级联删除全部回滚 事务验证 P0 TransactCtx

三、gRPC 接口测试用例

3.1 gRPC SyncPermissions

TC编号 接口/方法 测试场景 输入 预期结果 测试类型 优先级 覆盖说明
TC-0195 SyncPermissions 正常同步 valid req added/updated/disabled计数正确 正常路径 P0 permserver.go SyncPermissions
TC-0196 SyncPermissions appKey无效 invalid appKey codes.Unauthenticated 异常路径 P0 status.Error
TC-0197 SyncPermissions appSecret错误 wrong secret codes.Unauthenticated 异常路径 P0 status.Error
TC-0198 SyncPermissions 产品已禁用 disabled product codes.PermissionDenied 分支覆盖 P0 status.Error
TC-0199 SyncPermissions 验证disabled计数 DB有5条,perms含2条 disabled=3 功能验证 P0 RowsAffected

3.2 gRPC Login / RefreshToken / VerifyToken / GetUserPerms

TC编号 接口/方法 测试场景 输入 预期结果 测试类型 优先级 覆盖说明
TC-0200 Login 正常登录(普通用户+productCode) valid credentials + productCode token对+userInfo 正常路径 P0 permserver.go Login
TC-0201 Login 用户不存在 wrong username codes.Unauthenticated 异常路径 P0 status.Error
TC-0202 Login 密码错误 wrong password codes.Unauthenticated 异常路径 P0 status.Error
TC-0203 Login 账号冻结 frozen user codes.PermissionDenied 分支覆盖 P0 status.Error
TC-0204 Login 超管被拒绝 isSuperAdmin=1+productCode codes.PermissionDenied, "超级管理员不允许通过产品端登录" 安全 P0 IsSuperAdmin==1 → 拒绝
TC-0205 Login 普通用户+productCode 普通MEMBER+productCode perms含角色权限, memberType="MEMBER" 分支覆盖 P0 !isSuperAdmin && productCode!=""
TC-0206 Login 产品成员被禁用时拒绝登录 member.status=Disabled PermissionDenied 安全 P0 H-3: permserver Login
TC-0207 Login productCode为空 productCode="" codes.InvalidArgument, "productCode不能为空" 输入校验 P0 第一个校验点
TC-0208 RefreshToken 正常刷新 valid token 新token对 正常路径 P0 RefreshToken
TC-0209 RefreshToken token无效 invalid token codes.Unauthenticated 异常路径 P0 status.Error
TC-0210 RefreshToken 账号冻结 frozen codes.PermissionDenied 分支覆盖 P0 status.Error
TC-0211 RefreshToken productCode回退到claims req.ProductCode="", claims含productCode 使用claims.ProductCode 分支覆盖 P0 productCode==""回退
TC-0212 RefreshToken 超管+productCode isSuperAdmin=1+productCode memberType="SUPER_ADMIN", perms全量 分支覆盖 P0 isSuperAdmin && productCode!=""
TC-0213 RefreshToken 普通用户+productCode 普通MEMBER+productCode perms含角色权限 分支覆盖 P0 !isSuperAdmin && productCode!=""
TC-0214 VerifyToken 有效token valid valid=true, userId/perms正确 正常路径 P0 VerifyToken
TC-0215 VerifyToken 无效token invalid valid=false 异常路径 P0 err或!Valid
TC-0216 VerifyToken 缺少userId 伪造claims valid=false 安全 P0 !ok断言保护
TC-0217 VerifyToken 冻结用户token返回Invalid user.status=Disabled Valid=false 安全 P0 H-4: 实时查DB
TC-0218 VerifyToken 非成员token返回Invalid user非产品成员 Valid=false 安全 P0 H-4: 实时查成员状态
TC-0219 VerifyToken 返回实时MemberType和Perms DB中ADMIN+自定义权限 返回实时数据而非token中旧数据 安全 P0 H-4: 实时数据
TC-0220 GetUserPerms 用户不存在 userId=9999 codes.NotFound 异常路径 P0 status.Error
TC-0221 GetUserPerms 超管 isSuperAdmin perms全量, "SUPER_ADMIN" 正常路径 P0 GetUserPerms(true)
TC-0222 GetUserPerms MEMBER-DENY覆盖 角色有permA, DENY permA perms不含permA 深度业务 P0 denySet过滤

四、JWT中间件 / 统一响应测试用例

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0223 正常Bearer token Authorization: Bearer {valid} 通过, ctx注入5个值 正常路径 P0 middleware全路径
TC-0224 无Authorization头 无Header code=401, "未登录" 异常 P0 authHeader==""
TC-0225 无Bearer前缀 Authorization: xxx code=401, "token格式错误" 异常 P0 TrimPrefix相等
TC-0226 token签名错误 错误secret code=401, "token无效或已过期" 异常 P0 !Valid
TC-0227 token过期 expired code=401 异常 P0 jwt过期
TC-0228 claims类型断言失败 非标准claims code=401, "token无效或类型错误" 异常 P1 !ok 防御性分支,jwt.ParseWithClaims(&Claims{}) 下不可达;TokenType 检查由 TC-0229 覆盖
TC-0229 refresh token被拒绝 用refresh token访问API code=401, "token无效或类型错误" 安全 P0 TokenType="refresh"时拒绝
TC-0230 业务错误(CodeError) 触发404等 {code:业务码, msg:业务消息} 正常 P0 errors.As成功
TC-0231 内部错误 DB异常 {code:500, msg:"服务器内部错误"} 安全 P0 logx.Errorf+兜底
TC-0232 成功(有data) 正常请求 {code:0, msg:"ok", data:{...}} 正常 P0 v!=nil
TC-0233 成功(无data) 返回nil {code:0, msg:"ok"} 正常 P0 v==nil

五、util 层测试用例

5.1 NormalizePage

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0234 正常值 page=2, pageSize=10 (2, 10) 正常路径 P0 无修正
TC-0235 page<=0 page=0, pageSize=10 (1, 10) 边界 P0 page<=0→1
TC-0236 page=-1 page=-1, pageSize=10 (1, 10) 边界 P0 page<=0→1
TC-0237 pageSize<=0 page=1, pageSize=0 (1, 20) 边界 P0 pageSize<=0→20
TC-0238 pageSize>100 page=1, pageSize=500 (1, 100) 边界-上限 P0 pageSize>100→100
TC-0239 pageSize=100 page=1, pageSize=100 (1, 100) 边界 P1 恰好不触发
TC-0240 pageSize=101 page=1, pageSize=101 (1, 100) 边界 P1 恰好触发
TC-0241 双零 page=0, pageSize=0 (1, 20) 边界 P1 两条件同时

5.2 IsValidEmail

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0242 正常邮箱 [email protected] true 正常路径 P0 标准格式
TC-0243 含点号 [email protected] true 正常路径 P1 允许点号
TC-0244 含加号 [email protected] true 正常路径 P1 允许加号
TC-0245 缺少@ userexample.com false 异常路径 P0 无@
TC-0246 缺少域名 user@ false 异常路径 P0 无域名
TC-0247 缺少TLD user@example false 异常路径 P0 TLD<2字符
TC-0248 空字符串 "" false 边界 P1

5.3 IsValidPhone

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0249 国内手机号 13800138000 true 正常路径 P0 11位数字
TC-0250 带+国际码 +8613800138000 true 正常路径 P0 +前缀
TC-0251 太短(6位) 123456 false 边界 P0 <7位
TC-0252 恰好7位 1234567 true 边界 P1 最小长度
TC-0253 最长15位 +123456789012345 true 边界 P1 最大长度
TC-0254 超长16位 1234567890123456 false 边界 P1 超限
TC-0255 包含字母 1380013abc false 异常路径 P0 非数字
TC-0256 空字符串 "" false 边界 P1

六、Logic 层单元测试用例

以下针对 Logic 层中的核心共享函数,使用 mock Model 接口进行纯单元测试。

6.1 auth/jwt.go — GenerateAccessToken

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0257 正常生成 secret="s", expire=3600, userId=1, username="u", productCode="p", memberType="M", perms=["a"] 返回非空token, err=nil 正常路径 P0 jwt.NewWithClaims(HS256)
TC-0258 解析token验证claims 上述token ParseWithClaims可解析出正确userId/username/productCode/memberType/perms 功能验证 P0 claims完整性
TC-0259 空secret secret="" 仍能生成token(空key签名) 边界 P2 HS256 允许空key
TC-0260 空perms perms=nil token生成成功, 解析后perms=nil 边界 P1 nil slice
TC-0261 过期时间验证 expireSeconds=1, sleep 2s ParseWithClaims返回过期错误 功能验证 P0 ExpiresAt

6.2 auth/jwt.go — GenerateRefreshToken

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0262 正常生成 secret="s", expire=86400, userId=1, productCode="p" 返回非空token 正常路径 P0 RefreshClaims
TC-0263 解析验证 上述token ParseRefreshToken解析出userId=1, productCode="p" 功能验证 P0 往返一致
TC-0264 productCode为空 productCode="" 生成成功, 解析后productCode="" 边界 P1 空字符串

6.3 auth/jwt.go — ParseRefreshToken

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0265 正常解析 有效token+正确secret 返回RefreshClaims, err=nil 正常路径 P0 token.Valid
TC-0266 错误secret 有效token+错误secret err!=nil 异常路径 P0 签名验证失败
TC-0267 无效token字符串 "invalid-token" err!=nil 异常路径 P0 解析失败
TC-0268 空token "" err!=nil 边界 P1 空字符串
TC-0269 过期token 已过期的token err!=nil (token expired) 异常路径 P0 ExpiresAt已过
TC-0270 AccessToken误用 用AccessToken当RefreshToken解析 err!=nil (TokenType="access"≠"refresh") 安全 P0 TokenType字段校验

6.4 auth/perms.go — GetUserPerms

L-03重构GetUserPerms 已重构为直接委托 UserDetailsLoader.Load(),不再包含权限计算逻辑。 权限计算逻辑已迁移到 UserDetailsLoader 的测试中(第十章 TC-0494~TC-0506),此处仅需验证委托行为。

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0271 GetUserPerms委托到Loader userId+productCode 返回值等于UserDetailsLoader.Load().Perms和.MemberType, err=nil 正常路径 P0 L-03修复: 消除重复逻辑

6.5 middleware — 辅助函数单元测试

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0272 GetUserId-正常 ctx含userId=100 100 正常路径 P0 类型断言成功
TC-0273 GetUserId-空ctx 空ctx 0 边界 P0 断言失败→零值
TC-0274 GetUsername-正常 ctx含username="admin" "admin" 正常路径 P0 类型断言
TC-0275 GetUsername-空ctx 空ctx "" 边界 P0 零值
TC-0276 GetProductCode-正常 ctx含productCode="p1" "p1" 正常路径 P0 类型断言
TC-0277 GetMemberType-正常 ctx含memberType="ADMIN" "ADMIN" 正常路径 P0 类型断言
TC-0278 IsSuperAdmin-是 memberType="SUPER_ADMIN" true 正常路径 P0 ==
TC-0279 IsSuperAdmin-否 memberType="MEMBER" false 分支覆盖 P0 !=
TC-0280 IsSuperAdmin-空 无memberType false 边界 P1 零值

七、Model 层 _gen.go 模板生成方法测试用例

所有 9 个 Model 的 _gen.go 均由自定义模板 (cli/goctl/model/) 生成,包含非标准方法(批量操作、事务变体、buildBatchUpdateQuery 等)。 以下以 通用测试模式 列出,适用于全部 9 个 Model(注明差异部分)。

7.1 通用 CRUD 方法 (每个 Model 均需测试)

适用: SysUser, SysProduct, SysPerm, SysDept, SysRole, SysRolePerm, SysUserPerm, SysUserRole, SysProductMember

TC编号 方法 测试场景 预期结果 类型 优先级 覆盖说明
TC-0281 Insert 正常插入 返回Result+nil, DB有新记录 正常路径 P0 ExecCtx+缓存key清理
TC-0282 Insert 正常插入含TokenVersion err=nil, DB中tokenVersion=0(默认) 正常路径 P0 验证Insert包含tokenVersion
TC-0283 Insert 唯一索引冲突 返回DB错误(1062) 异常路径 P0 MySQL uk
TC-0284 Insert 缓存key生成正确 验证清理的缓存key包含主键和唯一索引 功能验证 P0 cacheSys*Prefix
TC-0285 InsertWithTx 事务内插入 使用session执行, 返回Result 正常路径 P0 session.ExecCtx
TC-0286 InsertWithTx 事务内插入含TokenVersion err=nil, 事务内可读到正确tokenVersion 正常路径 P0 验证InsertWithTx包含tokenVersion
TC-0287 InsertWithTx 事务回滚后无数据 事务内Insert+外部回滚→DB无记录 事务验证 P0 TransactCtx
TC-0288 FindOne 正常查询(缓存未命中) 返回记录, 缓存已写入 正常路径 P0 QueryRowCtx→DB
TC-0289 FindOne 正常查询(缓存命中) 不触发DB查询, 返回缓存数据 正常路径 P0 QueryRowCtx→cache
TC-0290 FindOne 记录不存在 返回ErrNotFound 异常路径 P0 sqlc.ErrNotFound→ErrNotFound
TC-0291 FindOne DB异常(非ErrNotFound) 返回原始error 异常路径 P1 default分支
TC-0292 FindOneWithTx 事务内正常查询 使用session.QueryRowCtx, 返回记录 正常路径 P0 session直查无缓存
TC-0293 FindOneWithTx 事务内记录不存在 返回ErrNotFound 异常路径 P0 sqlx.ErrNotFound
TC-0294 FindOneWithTx 事务内可见性 InsertWithTx后FindOneWithTx可读到 事务验证 P0 同session内可见
TC-0295 Update 正常更新 旧缓存key+新缓存key均被清理 正常路径 P0 FindOne→ExecCtx
TC-0296 Update 正常更新含TokenVersion err=nil, DB中tokenVersion正确更新 正常路径 P0 验证Update包含tokenVersion
TC-0297 Update 记录不存在 FindOne失败→返回ErrNotFound 异常路径 P0 FindOne err
TC-0298 UpdateWithTx 事务内更新 使用session, 缓存被清理 正常路径 P0 session.ExecCtx
TC-0299 Delete 正常删除 记录被删, 缓存key被清理 正常路径 P0 FindOne→ExecCtx DELETE
TC-0300 Delete 记录不存在 FindOne失败→返回ErrNotFound 异常路径 P0 FindOne err
TC-0301 DeleteWithTx 事务内删除 使用session, 缓存被清理 正常路径 P0 session.ExecCtx
TC-0302 TransactCtx 正常事务 fn执行成功→提交 正常路径 P0 conn.TransactCtx
TC-0303 TransactCtx fn返回错误 自动回滚 异常路径 P0 回滚
TC-0304 TableName 获取表名 返回正确表名(如 `sys_user`) 正常路径 P0 m.table

7.2 批量插入方法

TC编号 方法 测试场景 预期结果 类型 优先级 覆盖说明
TC-0305 BatchInsert 空列表 直接返回nil, 不执行SQL 边界 P0 len==0 early return
TC-0306 BatchInsert 单条记录 生成1组VALUES, 执行成功 正常路径 P0 单条
TC-0307 BatchInsert 多条记录(3条) 生成3组VALUES, SQL正确, 缓存key全清理 正常路径 P0 多条+缓存
TC-0308 BatchInsert 批量插入含TokenVersion err=nil, 所有记录tokenVersion正确 正常路径 P0 验证BatchInsert包含tokenVersion
TC-0309 BatchInsert 唯一索引冲突 全部失败, 返回DB错误 异常路径 P0 MySQL uk
TC-0310 BatchInsert 大批量(1000条) SQL长度合理, 执行成功 性能 P2 拼接性能
TC-0311 BatchInsertWithTx 空列表 直接返回nil 边界 P0 len==0
TC-0312 BatchInsertWithTx 正常多条 使用session执行 正常路径 P0 session.ExecCtx
TC-0313 BatchInsertWithTx 事务回滚 外部回滚→无新记录 事务验证 P0 TransactCtx

7.3 批量更新方法

TC编号 方法 测试场景 预期结果 类型 优先级 覆盖说明
TC-0314 BatchUpdate 空列表 直接返回nil 边界 P0 len==0 early return
TC-0315 BatchUpdate 单条记录 CASE-WHEN SQL正确, 更新成功 正常路径 P0 buildBatchUpdateQuery 单条
TC-0316 BatchUpdate 多条记录(3条) CASE-WHEN生成3个WHEN子句, 旧缓存key全清理 正常路径 P0 buildBatchUpdateQuery 多条
TC-0317 BatchUpdate 批量更新不污染数据 err=nil, tokenVersion/createTime/updateTime均正确 正常路径 P0 验证buildBatchUpdateQuery值对齐
TC-0318 BatchUpdate 部分id不存在 findListByPrimaryKeys返回部分→仅清理存在的缓存 边界 P1 oldList可能少于dataList
TC-0319 BatchUpdateWithTx 空列表 直接返回nil 边界 P0 len==0
TC-0320 BatchUpdateWithTx 正常多条 使用session执行 正常路径 P0 session.ExecCtx
TC-0321 buildBatchUpdateQuery 单条 SQL: UPDATE SET field=CASE WHEN id=? THEN ? ELSE field END WHERE id IN (?) 功能验证 P0 SQL结构
TC-0322 buildBatchUpdateQuery 多条 每个字段均有多个WHEN子句, WHERE IN含全部id 功能验证 P0 SQL正确性
TC-0323 buildBatchUpdateQuery vals数量正确 vals = N*(fields*2) + N (WHERE IN) 功能验证 P0 参数计数

7.4 批量删除方法

TC编号 方法 测试场景 预期结果 类型 优先级 覆盖说明
TC-0324 BatchDelete 空ids 直接返回nil 边界 P0 len==0 early return
TC-0325 BatchDelete 单个id DELETE WHERE id IN (?), 缓存清理 正常路径 P0 单条
TC-0326 BatchDelete 多个id(3个) 3个占位符, 旧数据查询→缓存key全清理 正常路径 P0 findListByPrimaryKeys
TC-0327 BatchDelete 包含不存在id findListByPrimaryKeys返回部分, 不报错 边界 P1 部分存在
TC-0328 BatchDeleteWithTx 空ids 直接返回nil 边界 P0 len==0
TC-0329 BatchDeleteWithTx 正常多条 使用session执行 正常路径 P0 session.ExecCtx

7.5 唯一索引查询方法 (按 Model 差异)

TC编号 Model 方法 测试场景 预期结果 优先级 覆盖说明
TC-0330 SysUser FindOneByUsername 正常查询 返回用户, 缓存写入 (索引缓存→主键缓存双层) P0 QueryRowIndexCtx
TC-0331 SysUser FindOneByUsername 不存在 返回ErrNotFound P0 sqlc.ErrNotFound
TC-0332 SysUser FindOneByUsernameWithTx 事务内正常查询 返回用户, 使用session直查 P0 session.QueryRowCtx
TC-0333 SysUser FindOneByUsernameWithTx 事务内不存在 返回ErrNotFound P0 sqlx.ErrNotFound
TC-0334 SysProduct FindOneByAppKey 正常查询 返回产品 P0 appKey唯一索引
TC-0335 SysProduct FindOneByAppKey 不存在 返回ErrNotFound P0
TC-0336 SysProduct FindOneByAppKeyWithTx 事务内正常查询 返回产品 P0 session直查
TC-0337 SysProduct FindOneByAppKeyWithTx 事务内不存在 返回ErrNotFound P0
TC-0338 SysProduct FindOneByCode 正常查询 返回产品 P0 code唯一索引
TC-0339 SysProduct FindOneByCode 不存在 返回ErrNotFound P0
TC-0340 SysProduct FindOneByCodeWithTx 事务内正常查询 返回产品 P0 session直查
TC-0341 SysProduct FindOneByCodeWithTx 事务内不存在 返回ErrNotFound P0
TC-0342 SysPerm FindOneByProductCodeCode 正常查询 返回权限(复合唯一索引) P0 productCode+code
TC-0343 SysPerm FindOneByProductCodeCode 不存在 返回ErrNotFound P0
TC-0344 SysPerm FindOneByProductCodeCodeWithTx 事务内正常查询 返回权限 P0 session直查
TC-0345 SysPerm FindOneByProductCodeCodeWithTx 事务内不存在 返回ErrNotFound P0
TC-0346 SysRole FindOneByProductCodeName 正常查询 返回角色(复合唯一索引) P0 productCode+name
TC-0347 SysRole FindOneByProductCodeName 不存在 返回ErrNotFound P0
TC-0348 SysRole FindOneByProductCodeNameWithTx 事务内正常查询 返回角色 P0 session直查
TC-0349 SysRole FindOneByProductCodeNameWithTx 事务内不存在 返回ErrNotFound P0
TC-0350 SysRolePerm FindOneByRoleIdPermId 正常查询 返回关联记录 P0 roleId+permId
TC-0351 SysRolePerm FindOneByRoleIdPermId 不存在 返回ErrNotFound P0
TC-0352 SysRolePerm FindOneByRoleIdPermIdWithTx 事务内正常查询 返回关联记录 P0 session直查
TC-0353 SysRolePerm FindOneByRoleIdPermIdWithTx 事务内不存在 返回ErrNotFound P0
TC-0354 SysUserPerm FindOneByUserIdPermId 正常查询 返回关联记录 P0 userId+permId
TC-0355 SysUserPerm FindOneByUserIdPermId 不存在 返回ErrNotFound P0
TC-0356 SysUserPerm FindOneByUserIdPermIdWithTx 事务内正常查询 返回关联记录 P0 session直查
TC-0357 SysUserPerm FindOneByUserIdPermIdWithTx 事务内不存在 返回ErrNotFound P0
TC-0358 SysUserRole FindOneByUserIdRoleId 正常查询 返回关联记录 P0 userId+roleId
TC-0359 SysUserRole FindOneByUserIdRoleId 不存在 返回ErrNotFound P0
TC-0360 SysUserRole FindOneByUserIdRoleIdWithTx 事务内正常查询 返回关联记录 P0 session直查
TC-0361 SysUserRole FindOneByUserIdRoleIdWithTx 事务内不存在 返回ErrNotFound P0
TC-0362 SysProductMember FindOneByProductCodeUserId 正常查询 返回成员记录 P0 productCode+userId
TC-0363 SysProductMember FindOneByProductCodeUserId 不存在 返回ErrNotFound P0
TC-0364 SysProductMember FindOneByProductCodeUserIdWithTx 事务内正常查询 返回成员记录 P0 session直查
TC-0365 SysProductMember FindOneByProductCodeUserIdWithTx 事务内不存在 返回ErrNotFound P0

7.6 内部辅助方法

TC编号 方法 测试场景 预期结果 类型 优先级 覆盖说明
TC-0366 findListByPrimaryKeys 空ids 返回空slice, 不执行SQL 边界 P0 len==0
TC-0367 findListByPrimaryKeys 正常ids 返回匹配记录(无缓存) 正常路径 P0 QueryRowsNoCacheCtx
TC-0368 findListByPrimaryKeys 部分不存在 仅返回存在的记录 边界 P1 IN查询
TC-0369 findListByPrimaryKeys DB异常 返回nil, err 异常路径 P1 err透传
TC-0370 getPrimaryKeyValue 正常 返回data.Id 功能验证 P0 interface{}
TC-0371 formatPrimary 正常 返回 "cache:sysXxx:id:{id}" 功能验证 P0 缓存key格式
TC-0372 queryPrimary 正常 执行 SELECT WHERE id=? 功能验证 P0 SQL

7.7 缓存key与前缀初始化

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0373 cachePrefix为空 cachePrefix="" 使用默认前缀 (如 "cache:sysUser:id:") 分支覆盖 P0 if cachePrefix!="" 未进入
TC-0374 cachePrefix非空 cachePrefix="test" 前缀变为 "test:cache:sysUser:id:" 分支覆盖 P0 if cachePrefix!="" 进入
TC-0375 多唯一索引前缀(SysProduct) cachePrefix="test" 3个缓存前缀均更新: id/appKey/code 功能验证 P0 3个变量均修改

八、Model 层自定义方法测试用例

8.1 SysUserModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0376 FindListByPage 正常分页 page=1, pageSize=10, DB有20条 返回10条+total=20 正常路径 P0 count+limit offset
TC-0377 FindListByPage 第二页 page=2, pageSize=10 offset=10, 返回后10条 正常路径 P0 (page-1)*pageSize
TC-0378 FindListByPage 空表 无数据 total=0, list为空 边界 P0 count=0
TC-0379 FindListByPage count查询失败 DB异常 返回0,0,err 异常路径 P1 第一个err
TC-0380 FindListByPage list查询失败 DB异常 返回0,total,err 异常路径 P1 第二个err
TC-0381 FindListByDeptIds 正常查询 deptIds=[1,2], page=1, pageSize=10 返回属于dept 1或2的用户 正常路径 P0 WHERE deptId IN
TC-0382 FindListByDeptIds 空deptIds deptIds=[] 返回nil,0,nil 边界 P0 len==0 early return
TC-0383 FindListByDeptIds 单个deptId deptIds=[1] IN(?)单值 正常路径 P1 单值
TC-0384 FindListByDeptIds deptId不存在 deptIds=[9999] total=0, list空 边界 P1 无匹配
TC-0385 FindByIds 正常批量查询 ids=[1,2,3] 返回3条 正常路径 P0 IN查询
TC-0386 FindByIds 空ids ids=[] 返回nil,nil 边界 P0 len==0
TC-0387 FindByIds 部分id不存在 ids=[1,9999] 仅返回存在的 边界 P1 IN不报错
TC-0388 FindByIds DB异常 连接失败 返回nil,err 异常路径 P1 err透传
TC-0389 FindIdsByDeptId 有用户的部门 deptId=1(有用户) 返回id列表 正常路径 P0 WHERE deptId=?
TC-0390 FindIdsByDeptId 无用户部门 deptId=999 空slice 边界 P1

8.2 SysProductModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0391 FindList 正常分页 page=1, pageSize=10 返回list+total 正常路径 P0 count+limit
TC-0392 FindList 空表 无数据 total=0, list空 边界 P0
TC-0393 FindList count失败 DB异常 返回err 异常路径 P1 第一个err

8.3 SysPermModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0394 FindListByProductCode 正常分页 productCode="p1", page=1, pageSize=10 list+total 正常路径 P0 WHERE productCode=?
TC-0395 FindListByProductCode 不存在的productCode "notexist" total=0, list空 边界 P1
TC-0396 FindAllByProductCode 正常查询(仅status=1) DB有status=1和status=2 仅返回status=1 正常路径 P0 AND status=1
TC-0397 FindAllByProductCode 无启用权限 全部status=2 返回空 边界 P1
TC-0398 FindAllCodesByProductCode 正常查询 DB有3条启用权限 返回3个code 正常路径 P0 SELECT code WHERE status=1
TC-0399 FindAllCodesByProductCode 空结果 无匹配 空slice 边界 P1
TC-0400 FindByIds 正常 ids=[1,2] 返回2条 正常路径 P0 IN查询
TC-0401 FindByIds 空ids [] 返回nil,nil 边界 P0 len==0
TC-0402 FindMapByProductCode 正常查询 productCode="p1" map[code]*SysPerm, key为code 正常路径 P0 result[p.Code]=p
TC-0403 FindMapByProductCode 空结果 无匹配 空map 边界 P1
TC-0404 FindMapByProductCode key唯一性 同productCode有3条 map长度=3 功能验证 P0 code唯一
TC-0405 DisableNotInCodes codes非空-正常 productCode="p1", codes=["a","b"], DB有a/b/c 禁用c, 返回affected=1 正常路径 P0 NOT IN
TC-0406 DisableNotInCodes codes为空-全部禁用 codes=[] 全部已启用的被禁用 分支覆盖 P0 len==0分支
TC-0407 DisableNotInCodes 无需禁用 codes包含所有已启用 affected=0 边界 P1 0行更新
TC-0408 DisableNotInCodes DB异常 连接失败 返回0,err 异常路径 P1 err
TC-0409 FindAllCodesByProductCode 有权限产品 productCode="p1" 返回code列表(仅status=1) 正常路径 P0 WHERE status=1
TC-0410 FindAllCodesByProductCode 无权限产品 productCode="notexist" 空slice 边界 P1

8.4 SysDeptModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0411 FindAll 正常查询 DB有5条 返回5条, 按sort asc排序 正常路径 P0 ORDER BY sort, id
TC-0412 FindAll 空表 无数据 空slice 边界 P0
TC-0413 FindByParentId 正常查询 parentId=1 返回子部门列表 正常路径 P0 WHERE parentId=?
TC-0414 FindByParentId 无子部门 parentId=999 空slice 边界 P1
TC-0415 FindByPathPrefix 正常查询 pathPrefix="/1/" 返回路径以/1/开头的部门 正常路径 P0 LIKE pathPrefix%
TC-0416 FindByPathPrefix LIKE注入已阻止 pathPrefix含% 空slice(%和_已转义,不作为通配符) 安全 P1 NewReplacer转义
TC-0417 FindByPathPrefix 无匹配 "/999/" 空slice 边界 P1

8.5 SysRoleModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0418 FindListByProductCode 正常分页 productCode="p1" 按permsLevel asc排序 正常路径 P0 ORDER BY permsLevel, id
TC-0419 FindListByProductCode 空结果 无匹配 total=0 边界 P1
TC-0420 FindByIds 正常 ids=[1,2] 返回2条 正常路径 P0 IN查询
TC-0421 FindByIds 空ids [] 返回nil,nil 边界 P0 len==0
TC-0422 FindMinPermsLevelByUserIdAndProductCode 有角色用户 userId=1, productCode="p1" 返回最小permsLevel 正常路径 P0 MIN聚合
TC-0423 FindMinPermsLevelByUserIdAndProductCode 无角色用户 userId=无角色用户 error(ErrNotFound) 边界 P0 IFNULL返回-1→level<0→ErrNotFound

8.6 SysRolePermModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0424 FindPermIdsByRoleId 正常查询 roleId=1, DB有3条 返回3个permId 正常路径 P0 SELECT permId WHERE roleId=?
TC-0425 FindPermIdsByRoleId 无绑定 roleId=999 空slice 边界 P1
TC-0426 FindPermIdsByRoleIds 正常查询 roleIds=[1,2] 返回去重后的permId 正常路径 P0 DISTINCT + IN
TC-0427 FindPermIdsByRoleIds 空roleIds [] 返回nil,nil 边界 P0 len==0
TC-0428 FindPermIdsByRoleIds 去重验证 两角色有相同permId 结果中permId不重复 功能验证 P0 DISTINCT
TC-0429 DeleteByRoleId 正常删除 roleId=1 删除该角色所有权限绑定 正常路径 P0 ExecNoCacheCtx (不清缓存)
TC-0430 DeleteByRoleId 无绑定 roleId=999 删0行, 不报错 边界 P1
TC-0431 DeleteByRoleIdTx 正常事务内删除 session+roleId 使用session执行 正常路径 P0 session.ExecCtx

8.7 SysUserPermModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0432 FindByUserId 正常查询 userId=1 返回该用户所有权限配置 正常路径 P0 WHERE userId=?
TC-0433 FindByUserId 无记录 userId=999 空slice 边界 P1
TC-0434 FindPermIdsByUserIdAndEffect ALLOW userId=1, effect="ALLOW" 返回ALLOW的permIds 正常路径 P0 AND effect=?
TC-0435 FindPermIdsByUserIdAndEffect DENY userId=1, effect="DENY" 返回DENY的permIds 正常路径 P0 effect="DENY"
TC-0436 FindPermIdsByUserIdAndEffect 无记录 无匹配 空slice 边界 P1
TC-0437 DeleteByUserId 正常删除 userId=1 删除该用户所有权限配置 正常路径 P0 ExecNoCacheCtx
TC-0438 DeleteByUserIdTx 事务内删除 session+userId 使用session 正常路径 P0 session.ExecCtx
TC-0439 DeleteByUserIdForProduct 正常删除 userId=1, productCode="p1" 仅删除该产品下的权限配置 正常路径 P0 子查询 sys_perm.productCode
TC-0440 DeleteByUserIdForProduct 跨产品隔离 用户在多产品有配置 仅删目标产品的 深度业务 P0 子查询隔离
TC-0441 DeleteByUserIdForProductTx 事务内跨产品删除 session+userId+productCode 使用session 正常路径 P0 session.ExecCtx

8.8 SysUserRoleModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0442 FindRoleIdsByUserId 正常查询 userId=1, DB有3条 返回3个roleId 正常路径 P0 SELECT roleId
TC-0443 FindRoleIdsByUserId 无绑定 userId=999 空slice 边界 P1
TC-0444 FindByUserId 正常查询 userId=1 返回完整SysUserRole列表 正常路径 P0 SELECT *
TC-0445 DeleteByUserId 正常删除 userId=1 删除该用户所有角色绑定 正常路径 P0 ExecNoCacheCtx
TC-0446 DeleteByUserIdTx 事务内删除 session+userId 使用session 正常路径 P0 session.ExecCtx
TC-0447 DeleteByRoleIdTx 正常删除 session+roleId 删除该角色的所有用户绑定 正常路径 P0 session.ExecCtx
TC-0448 DeleteByUserIdForProduct 正常删除 userId=1, productCode="p1" 仅删该产品下角色绑定 正常路径 P0 子查询 sys_role.productCode
TC-0449 DeleteByUserIdForProduct 跨产品隔离 用户在多产品有角色 仅删目标产品的 深度业务 P0 子查询隔离
TC-0450 DeleteByUserIdForProductTx 事务内跨产品删除 session+userId+productCode 使用session 正常路径 P0 session.ExecCtx
TC-0451 FindUserIdsByRoleId 有绑定的角色 roleId=1 返回userId列表 正常路径 P0 WHERE roleId=?
TC-0452 FindUserIdsByRoleId 无绑定角色 roleId=999 空slice 边界 P1

8.9 SysProductMemberModel

TC编号 方法 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0453 FindListByProductCode 正常分页 productCode="p1" list+total 正常路径 P0 WHERE productCode=?
TC-0454 FindListByProductCode 空结果 无匹配 total=0 边界 P1
TC-0455 FindByUserId 正常查询 userId=1 返回用户所有产品成员身份 正常路径 P0 WHERE userId=?
TC-0456 FindByUserId 无成员身份 userId=999 空slice 边界 P1
TC-0457 FindMapByProductCodeUserIds 正常批量 productCode="p1", userIds=[1,2] map key=userId 正常路径 P0 IN+productCode
TC-0458 FindMapByProductCodeUserIds 空userIds [] 返回空map 边界 P0 len==0
TC-0459 FindMapByProductCodeUserIds 部分不是成员 userIds含非成员 map仅含成员 边界 P1
TC-0460 FindMapByProductCodeUserIds map key正确 查询结果 key=userId, val=*SysProductMember 功能验证 P0 result[pm.UserId]

九、访问控制 (auth/access.go)

9.1 RequireSuperAdmin

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0461 超管通过 ctx含SuperAdmin UserDetails nil (允许) 正常路径 P0 caller.IsSuperAdmin
TC-0462 非超管拒绝 ctx含ADMIN UserDetails 403 "仅超级管理员" 异常路径 P0 !IsSuperAdmin
TC-0463 MEMBER拒绝 ctx含MEMBER UserDetails 403 "仅超级管理员" 异常路径 P0
TC-0464 未登录 ctx无UserDetails 401 "未登录" 边界 P0 caller==nil

9.2 RequireProductAdmin

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0465 超管通过 ctx含SuperAdmin nil 正常路径 P0 IsSuperAdmin
TC-0466 ADMIN通过 ctx含ADMIN nil 正常路径 P0 MemberType==ADMIN
TC-0467 DEVELOPER拒绝 ctx含DEVELOPER 403 异常路径 P0 非Admin
TC-0468 MEMBER拒绝 ctx含MEMBER 403 异常路径 P0 非Admin
TC-0469 未登录 ctx无UserDetails 401 边界 P0 caller==nil

9.3 CheckMemberTypeAssignment

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0470 超管可分配任何类型 caller=SuperAdmin, assigned=ADMIN nil 正常路径 P0 IsSuperAdmin豁免
TC-0471 ADMIN分配DEVELOPER caller=ADMIN, assigned=DEVELOPER nil 正常路径 P0 callerPri(1) < assignPri(2)
TC-0472 ADMIN分配ADMIN(同级拒绝) caller=ADMIN, assigned=ADMIN 403 深度业务 P0 callerPri >= assignPri
TC-0473 DEVELOPER分配ADMIN(越级拒绝) caller=DEVELOPER, assigned=ADMIN 403 深度业务 P0 callerPri > assignPri
TC-0474 MEMBER分配MEMBER(同级拒绝) caller=MEMBER, assigned=MEMBER 403 深度业务 P0
TC-0475 未登录 ctx无UserDetails 401 边界 P0

9.4 CheckManageAccess

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0476 超管可管理任何人 caller=SuperAdmin nil 正常路径 P0 IsSuperAdmin豁免
TC-0477 操作自己 caller.UserId==targetUserId nil 正常路径 P0 self豁免
TC-0478 ADMIN跳过部门检查 caller=ADMIN nil (直接比级别) 深度业务 P0 checkDeptHierarchy ADMIN豁免
TC-0479 非ADMIN无部门拒绝 caller.DeptId=0 403 "未归属部门" 边界 P0 caller.DeptId==0
TC-0480 目标用户无部门 target.DeptId=0 403 "目标用户未归属部门" 边界 P0 target.DeptId==0
TC-0481 目标在不同部门 目标不在caller子部门 403 "无权管理其他部门" 深度业务 P0 !HasPrefix
TC-0482 未登录 ctx无UserDetails 401 边界 P0
TC-0483 caller.DeptPath为空时拒绝 caller有DeptId但DeptPath="" 403 "无权管理" 安全 P0 H-08修复: DeptPath空串保护

9.5 memberTypePriority

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0484 各类型优先级正确 全部4种+未知 SA=0,A=1,D=2,M=3,unknown=MaxInt32 白盒 P0 switch分支

十、UserDetailsLoader (loaders/userDetailsLoader.go)

10.1 Load / 缓存

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0485 DB加载(缓存miss) 有效userId+productCode 返回完整UserDetails 正常路径 P0 loadFromDB全链路
TC-0486 缓存命中 第二次Load同key 从Redis返回,不查DB 正常路径 P0 GetCtx hit
TC-0487 用户不存在 userId=999999 返回零值UserDetails(Status=0) 边界 P0 loadUser失败
TC-0488 productCode为空 productCode="" 跳过产品/成员/角色/权限加载 边界 P1 各方法guard

10.2 缓存失效

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0489 Del删除指定缓存 Del(uid, pc) 缓存被删除,下次Load查DB 正常路径 P0 DelCtx
TC-0490 Clean清除用户所有产品缓存 Clean(uid) 该用户所有key被删 正常路径 P0 KEYS pattern
TC-0491 CleanByProduct清除产品所有用户 CleanByProduct(pc) 该产品所有key被删 正常路径 P0 KEYS pattern
TC-0492 BatchDel批量删除 BatchDel([uid1,uid2], pc) 多个key被删 正常路径 P0 DelCtx多key
TC-0493 BatchDel空数组 BatchDel([], pc) 无操作 边界 P1 len==0 guard

10.3 loadPerms权限计算

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0494 超管全量权限 IsSuperAdmin=true Perms=全部启用的权限码 正常路径 P0 超管分支
TC-0495 ADMIN全量权限 MemberType=ADMIN Perms=全量 正常路径 P0 ADMIN分支
TC-0496 DEVELOPER全量权限 MemberType=DEVELOPER Perms=全量 正常路径 P0 DEVELOPER分支
TC-0497 DEV部门全量权限 DeptType=DEV Perms=全量 正常路径 P0 DeptTypeDev分支
TC-0498 MEMBER角色权限+ALLOW-DENY 有角色+ALLOW+DENY 正确计算 深度业务 P0 denySet过滤
TC-0499 用户ALLOW权限不跨产品泄漏 用户在产品A/B各有ALLOW权限 加载产品A时仅含A权限,不含B权限 安全 P0 H-1: FindPermIdsByUserIdAndEffectForProduct
TC-0500 禁用DEV部门成员无全量权限 dept.type=DEV, dept.status=Disabled ud.Perms为空 安全 P0 M-3: DeptStatus检查

10.4 loadRoles + MinPermsLevel

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0501 多角色取最小permsLevel 用户有level=10和level=5的角色 MinPermsLevel=5 正常路径 P0 min计算
TC-0502 无角色 用户无角色 MinPermsLevel=MaxInt64 边界 P0 默认值
TC-0503 角色跨产品过滤 角色在不同产品 仅加载当前产品角色 深度业务 P0 productCode过滤
TC-0504 禁用角色不计入 角色status=2 不在Roles列表中 深度业务 P0 Status==Enabled

10.5 loadMembership

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0505 超管自动设置SUPER_ADMIN IsSuperAdmin=true MemberType=SUPER_ADMIN, 不查DB 正常路径 P0 早期return
TC-0506 非成员MemberType为空 用户非该产品成员 MemberType="" 边界 P0 ErrNotFound
TC-0507 禁用成员MemberType为空 member.status=Disabled ud.MemberType="" 安全 P0 H-3: loadMembership

十一、中间件 — 冻结账号拦截

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0508 冻结用户被403 有效token但Status=2 code=403 "账号已被冻结" 安全 P0 ud.Status!=Enabled
TC-0509 用户不存在(Status=0) token中userId不存在 code=403 "账号已被冻结" 安全 P0 loadUser失败→Status=0
TC-0510 UserDetails注入context 正常请求 GetUserDetails(ctx)非nil 正常路径 P0 WithUserDetails

十二、Logic层 — 访问控制负面测试

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0511 createDept非超管拒绝 ctx=ADMIN 403 "仅超级管理员" 安全 P0 RequireSuperAdmin
TC-0512 updateDept非超管拒绝 ctx=ADMIN 403 "仅超级管理员" 安全 P0 RequireSuperAdmin
TC-0513 deleteDept非超管拒绝 ctx=ADMIN 403 "仅超级管理员" 安全 P0 RequireSuperAdmin
TC-0514 createProduct非超管拒绝 ctx=ADMIN 403 "仅超级管理员" 安全 P0 RequireSuperAdmin
TC-0515 updateProduct非超管拒绝 ctx=ADMIN 403 "仅超级管理员" 安全 P0 RequireSuperAdmin
TC-0516 createUser非产品管理员拒绝 ctx=MEMBER 403 "仅超级管理员或产品管理员" 安全 P0 RequireProductAdmin
TC-0517 createRole非产品管理员拒绝 ctx=MEMBER 403 安全 P0 RequireProductAdmin
TC-0518 updateRole非产品管理员拒绝 ctx=MEMBER 403 安全 P0 RequireProductAdmin
TC-0519 deleteRole非产品管理员拒绝 ctx=MEMBER 403 安全 P0 RequireProductAdmin
TC-0520 bindRolePerms非产品管理员拒绝 ctx=MEMBER 403 安全 P0 RequireProductAdmin
TC-0521 updateUser-MEMBER不能管理他人 ctx=MEMBER, id!=self 403 (CheckManageAccess拒绝) 安全 P0 Audit#4修复: CheckManageAccess权限校验
TC-0522 updateUser自己修改DeptId被拒绝 ctx含userId=X, req.Id=X, req.DeptId!=nil 403 "不允许修改自己的部门和状态" 安全 P0 H-01修复: 自编辑限制DeptId
TC-0523 updateUser自己修改Status被拒绝 ctx含userId=X, req.Id=X, req.Status!=0 403 "不允许修改自己的部门和状态" 安全 P0 H-01修复: 自编辑限制Status
TC-0524 updateUser未登录被拒绝 ctx无UserDetails 401 "未登录" 安全 P0 H-01修复: caller==nil

十三、限流中间件 (middleware/ratelimitMiddleware.go)

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0525 正常请求(未超限) 首次请求 请求正常通过, next被调用 正常路径 P0 code!=OverQuota→next
TC-0526 超限请求被拒绝 超出配额后的请求 code=429, "请求过于频繁,请稍后再试" 异常路径 P0 code==OverQuota→ErrTooManyRequests
TC-0527 behindProxy=false时XFF被忽略 behindProxy=false, 不同XFF头+相同RemoteAddr 仍被限流, nextCount保持为1 安全 P0 behindProxy=false: 仅用RemoteAddr
TC-0528 behindProxy=false时X-Real-IP被忽略 behindProxy=false, 不同XRI头+相同RemoteAddr 仍被限流, nextCount保持为1 安全 P0 behindProxy=false: 仅用RemoteAddr
TC-0529 IP从RemoteAddr解析 无代理头, RemoteAddr="ip:port" 使用SplitHostPort解析host作为限流key 分支覆盖 P0 SplitHostPort解析host
TC-0530 不同IP独立限流 两个不同IP 各自独立计数, 互不影响 功能验证 P0 key隔离
TC-0531 behindProxy=true时信任X-Real-IP behindProxy=true, 不同X-Real-IP头 按X-Real-IP独立限流 正常路径 P0 behindProxy=true: X-Real-IP优先
TC-0532 behindProxy=true时无X-Real-IP回退RemoteAddr behindProxy=true, 无X-Real-IP头 使用RemoteAddr作为限流key 分支覆盖 P0 X-Real-IP为空→fallback RemoteAddr
TC-0533 behindProxy=true时XFF仍被忽略 behindProxy=true, XFF头+无X-Real-IP 按RemoteAddr限流, XFF不影响 安全 P0 仅信任X-Real-IP, 不信任XFF
TC-0534 RemoteAddr无端口格式 RemoteAddr="1.2.3.4"(无端口) 返回原始RemoteAddr "1.2.3.4" 边界 P1 SplitHostPort失败→r.RemoteAddr

十四、审计修复验证 (Audit Fix Verification)

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0535 updateUser-产品管理员可管理范围内用户 ctx=ADMIN, target在管理范围内 更新成功 正常路径 P0 Audit#4修复: CheckManageAccess允许产品管理员
TC-0536 updateUser-昵称超长拒绝 nickname=65字符 400 "昵称长度不能超过64个字符" 边界 P1 输入校验
TC-0537 updateUser-部门不存在 deptId=999999 400 "部门不存在" 异常路径 P1 关联对象不存在校验
TC-0538 userList-非超管仅可见产品成员 ctx=ADMIN(非超管), productCode指定 仅返回该产品成员, 不返回非成员 安全 P0 Audit#1修复: FindListByProductMembers数据隔离
TC-0539 userList-非超管未指定productCode被拒绝 ctx=ADMIN(非超管), productCode="" 403 "非超管用户必须指定产品编码" 安全 P0 Audit#1修复: 强制productCode
TC-0540 userList-非超管使用错误productCode被拒绝 ctx=ADMIN, productCode!=ctx.ProductCode 403 安全 P0 Audit#1修复: productCode一致性校验
TC-0541 bindRoles-permsLevel越权拒绝 ctx=ADMIN(MinPermsLevel=50), role.permsLevel=1 403 "不能分配权限级别高于自身的角色" 安全 P0 Audit#2修复: 角色权限级别越权防护
TC-0542 bindRoles-超管可分配任意级别角色 ctx=SuperAdmin, role.permsLevel=1 绑定成功 正常路径 P0 Audit#2修复: 超管无permsLevel限制

十五、补充测试用例 — 输入校验 / 安全 / 业务约束

15.1 RefreshToken 安全增强

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0543 TokenVersion不匹配时拒绝刷新 refreshToken含tokenVersion=999, DB中tokenVersion=0 401 "登录状态已失效,请重新登录" 安全 P0 claims.TokenVersion != ud.TokenVersion
TC-0544 使用accessToken作为refreshToken被拒绝 用accessSecret签发的accessToken作为refreshToken传入 401 "refreshToken无效或已过期" 安全 P0 ParseRefreshToken校验TokenType!=refresh
TC-0545 产品成员已移除时拒绝刷新 refreshToken含productCode, 但用户已从该产品移除 403 "您已不是该产品的成员" 安全 P0 ud.MemberType=="" && !ud.IsSuperAdmin

15.2 CreateUser 输入校验增强

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0546 用户名含特殊字符被拒绝 {"username":"user@name!","password":"pass123456"} 400 "用户名只能包含字母、数字和下划线,长度2-64个字符" 输入校验 P0 usernameRegexp不匹配
TC-0547 用户名太短(1字符)被拒绝 {"username":"a","password":"pass123456"} 400 "用户名只能包含字母、数字和下划线,长度2-64个字符" 边界值 P0 最小长度2
TC-0548 用户名太长(65字符)被拒绝 {"username":"a*65","password":"pass123456"} 400 "用户名只能包含字母、数字和下划线,长度2-64个字符" 边界值 P0 最大长度64
TC-0549 部门不存在被拒绝 {"username":"x","password":"pass123456","deptId":999999999} 400 "部门不存在" 异常路径 P1 DeptId>0时校验FindOne
TC-0550 昵称超过64字符被拒绝 {"username":"x","password":"pass123456","nickname":"n*65"} 400 "昵称长度不能超过64个字符" 边界值 P1 len(Nickname)>64
TC-0551 备注超过255字符被拒绝 {"username":"x","password":"pass123456","remark":"r*256"} 400 "备注长度不能超过255个字符" 边界值 P1 len(Remark)>255

15.3 SetUserPerms 业务约束增强

TC编号 测试场景 输入 预期结果 类型 优先级 覆盖说明
TC-0552 同一权限ID冲突Effect被拒绝 perms含[{permId:1,effect:"ALLOW"},{permId:1,effect:"DENY"}] 400 "同一权限ID不能同时为 ALLOW 和 DENY" 业务约束 P0 seen[permId]冲突检测
TC-0553 重复权限ID相同Effect去重 perms含[{permId:1,effect:"ALLOW"},{permId:1,effect:"ALLOW"}] 成功, DB仅1条记录 数据鲁棒性 P1 seen去重,uniquePerms
TC-0554 已禁用权限不能被设置 perm.Status=2(Disabled) 400 "权限 xxx 已被禁用,无法设置" 业务约束 P0 p.Status != StatusEnabled