package dept import ( "context" "errors" "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" "github.com/zeromicro/go-zero/core/stores/sqlx" "go.uber.org/mock/gomock" ) type fakeResult struct{ id int64 } func (r fakeResult) LastInsertId() (int64, error) { return r.id, nil } func (r fakeResult) RowsAffected() (int64, error) { return 1, nil } // TC-0085: 事务回滚-Insert失败 func TestCreateDept_Mock_InsertWithTxFail(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() dbErr := errors.New("db error") mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().TransactCtx(gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, fn func(context.Context, sqlx.Session) error) error { return fn(ctx, nil) }) mockDept.EXPECT().InsertWithTx(gomock.Any(), nil, gomock.Any()). Return(nil, dbErr) svcCtx := mocks.NewMockServiceContext(mocks.MockModels{ Dept: mockDept, }) logic := NewCreateDeptLogic(ctxhelper.SuperAdminCtx(), svcCtx) resp, err := logic.CreateDept(&types.CreateDeptReq{ ParentId: 0, Name: "TestDept", }) assert.Error(t, err) assert.ErrorIs(t, err, dbErr) assert.Nil(t, resp) } // TC-0082: 不传DeptType默认NORMAL func TestCreateDept_Mock_DefaultDeptType(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().TransactCtx(gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, fn func(context.Context, sqlx.Session) error) error { return fn(ctx, nil) }) mockDept.EXPECT().InsertWithTx(gomock.Any(), nil, gomock.Any()). DoAndReturn(func(ctx context.Context, s sqlx.Session, data *deptModel.SysDept) (interface{ LastInsertId() (int64, error); RowsAffected() (int64, error) }, error) { assert.Equal(t, "NORMAL", data.DeptType) return fakeResult{id: 99}, nil }) mockDept.EXPECT().FindOneWithTx(gomock.Any(), nil, int64(99)). Return(&deptModel.SysDept{Id: 99, Path: "/", DeptType: "NORMAL"}, nil) mockDept.EXPECT().UpdateWithTx(gomock.Any(), nil, gomock.Any()).Return(nil) svcCtx := mocks.NewMockServiceContext(mocks.MockModels{Dept: mockDept}) logic := NewCreateDeptLogic(ctxhelper.SuperAdminCtx(), svcCtx) resp, err := logic.CreateDept(&types.CreateDeptReq{ ParentId: 0, Name: "TestDept", }) assert.NoError(t, err) assert.NotNil(t, resp) } // TC-0083: 传DeptType=DEV func TestCreateDept_Mock_DevDeptType(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().TransactCtx(gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, fn func(context.Context, sqlx.Session) error) error { return fn(ctx, nil) }) mockDept.EXPECT().InsertWithTx(gomock.Any(), nil, gomock.Any()). DoAndReturn(func(ctx context.Context, s sqlx.Session, data *deptModel.SysDept) (interface{ LastInsertId() (int64, error); RowsAffected() (int64, error) }, error) { assert.Equal(t, "DEV", data.DeptType) return fakeResult{id: 100}, nil }) mockDept.EXPECT().FindOneWithTx(gomock.Any(), nil, int64(100)). Return(&deptModel.SysDept{Id: 100, Path: "/", DeptType: "DEV"}, nil) mockDept.EXPECT().UpdateWithTx(gomock.Any(), nil, gomock.Any()).Return(nil) svcCtx := mocks.NewMockServiceContext(mocks.MockModels{Dept: mockDept}) logic := NewCreateDeptLogic(ctxhelper.SuperAdminCtx(), svcCtx) resp, err := logic.CreateDept(&types.CreateDeptReq{ ParentId: 0, Name: "TestDevDept", DeptType: "DEV", }) assert.NoError(t, err) assert.NotNil(t, resp) } // TC-0086: 事务回滚-UpdateWithTx失败 func TestCreateDept_Mock_UpdateWithTxFail(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() dbErr := errors.New("db error") mockDept := mocks.NewMockSysDeptModel(ctrl) mockDept.EXPECT().TransactCtx(gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, fn func(context.Context, sqlx.Session) error) error { return fn(ctx, nil) }) mockDept.EXPECT().InsertWithTx(gomock.Any(), nil, gomock.Any()). Return(fakeResult{id: 99}, nil) mockDept.EXPECT().FindOneWithTx(gomock.Any(), nil, int64(99)). Return(&deptModel.SysDept{Id: 99, Path: "/"}, nil) mockDept.EXPECT().UpdateWithTx(gomock.Any(), nil, gomock.Any()). Return(dbErr) svcCtx := mocks.NewMockServiceContext(mocks.MockModels{ Dept: mockDept, }) logic := NewCreateDeptLogic(ctxhelper.SuperAdminCtx(), svcCtx) resp, err := logic.CreateDept(&types.CreateDeptReq{ ParentId: 0, Name: "TestDept", }) assert.Error(t, err) assert.ErrorIs(t, err, dbErr) assert.Nil(t, resp) }