package dept import ( "testing" deptModel "perms-system-server/internal/model/dept" "perms-system-server/internal/testutil/ctxhelper" "perms-system-server/internal/testutil/mocks" "perms-system-server/internal/types" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" ) // TC-0105: UpdateDept 只清理自身部门用户缓存,不再级联到子部门 (audit 修复验证) func TestUpdateDept_Mock_CascadeCacheClean(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() parentDeptId := int64(10) mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().FindOne(gomock.Any(), parentDeptId). Return(&deptModel.SysDept{ Id: parentDeptId, Name: "Parent", Path: "/10/", DeptType: "NORMAL", Status: 1, UpdateTime: 1000, }, nil) // 修复后:使用乐观锁 UpdateWithOptLock,且不再调用 FindByPathPrefix mockDept.EXPECT().UpdateWithOptLock(gomock.Any(), gomock.Any(), int64(1000)).Return(nil) mockUser := mocks.NewMockSysUserModel(ctrl) // 修复后:仅查询目标部门直属用户,不再级联查询子部门用户 mockUser.EXPECT().FindIdsByDeptId(gomock.Any(), parentDeptId). Return([]int64{100, 101}, nil) // 下面两个调用不应发生(gomock 默认严格,未声明调用即失败) svcCtx := mocks.NewMockServiceContext(mocks.MockModels{ Dept: mockDept, User: mockUser, }) ctx := ctxhelper.SuperAdminCtx() logic := NewUpdateDeptLogic(ctx, svcCtx) err := logic.UpdateDept(&types.UpdateDeptReq{ Id: parentDeptId, Name: "Parent Updated", DeptType: "DEV", }) assert.NoError(t, err) } // TC-0714: UpdateDept 当 deptType 与 status 都未变化时,不触发任何缓存清理 (audit ) func TestUpdateDept_Mock_NoCacheCleanWhenUnchanged(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() deptId := int64(11) mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().FindOne(gomock.Any(), deptId). Return(&deptModel.SysDept{ Id: deptId, Name: "Old", Path: "/11/", DeptType: "NORMAL", Status: 1, UpdateTime: 2000, }, nil) mockDept.EXPECT().UpdateWithOptLock(gomock.Any(), gomock.Any(), int64(2000)).Return(nil) mockUser := mocks.NewMockSysUserModel(ctrl) // 不应调用 FindIdsByDeptId — 未设置期望,任何调用都会 FAIL svcCtx := mocks.NewMockServiceContext(mocks.MockModels{ Dept: mockDept, User: mockUser, }) ctx := ctxhelper.SuperAdminCtx() logic := NewUpdateDeptLogic(ctx, svcCtx) err := logic.UpdateDept(&types.UpdateDeptReq{ Id: deptId, Name: "New Name", DeptType: "NORMAL", // 与原值一致 Status: 1, // 与原值一致 }) assert.NoError(t, err) } // TC-0715: UpdateDept 乐观锁冲突时返回 409 ErrConflict (audit 乐观锁补充) func TestUpdateDept_Mock_OptLockConflict(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() deptId := int64(12) mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().FindOne(gomock.Any(), deptId). Return(&deptModel.SysDept{ Id: deptId, Name: "Old", Path: "/12/", DeptType: "NORMAL", Status: 1, UpdateTime: 3000, }, nil) // 模拟并发:另一事务已更新该行,updateTime 不再匹配 mockDept.EXPECT().UpdateWithOptLock(gomock.Any(), gomock.Any(), int64(3000)). Return(deptModel.ErrUpdateConflict) svcCtx := mocks.NewMockServiceContext(mocks.MockModels{ Dept: mockDept, }) ctx := ctxhelper.SuperAdminCtx() logic := NewUpdateDeptLogic(ctx, svcCtx) err := logic.UpdateDept(&types.UpdateDeptReq{ Id: deptId, Name: "new", }) assert.Error(t, err) // 期望 409 Conflict assert.Contains(t, err.Error(), "数据已被其他操作修改") }