backend/pkg/permission/usecase/user_role_usecase_test.go

468 lines
11 KiB
Go

package usecase
import (
"backend/pkg/permission/domain"
"backend/pkg/permission/domain/entity"
"backend/pkg/permission/domain/usecase"
mockRepo "backend/pkg/permission/mock/repository"
"context"
"errors"
"testing"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/mock/gomock"
)
func TestUserRoleUseCase_Assign(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockUserRoleRepo := mockRepo.NewMockUserRoleRepository(mockCtrl)
mockRoleRepo := mockRepo.NewMockRoleRepository(mockCtrl)
uc := NewUserRoleUseCase(UserRoleUseCaseParam{
UserRoleRepo: mockUserRoleRepo,
RoleRepo: mockRoleRepo,
})
ctx := context.Background()
tests := []struct {
name string
req usecase.AssignRoleRequest
mockSetup func()
wantErr bool
}{
{
name: "成功指派角色",
req: usecase.AssignRoleRequest{
UserUID: "user123",
RoleUID: "ROLE0000000001",
Brand: "brand1",
},
mockSetup: func() {
role := &entity.Role{
ID: bson.NewObjectID(),
UID: "ROLE0000000001",
Name: "管理員",
Status: domain.RecordActive,
}
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE0000000001").Return(role, nil)
mockUserRoleRepo.EXPECT().Exists(ctx, "user123").Return(false, nil)
mockUserRoleRepo.EXPECT().Create(ctx, gomock.Any()).Return(nil)
},
wantErr: false,
},
{
name: "角色不存在",
req: usecase.AssignRoleRequest{
UserUID: "user456",
RoleUID: "ROLE9999999999",
},
mockSetup: func() {
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE9999999999").Return(nil, errors.New("not found"))
},
wantErr: true,
},
{
name: "角色未啟用",
req: usecase.AssignRoleRequest{
UserUID: "user789",
RoleUID: "ROLE0000000002",
},
mockSetup: func() {
role := &entity.Role{
ID: bson.NewObjectID(),
UID: "ROLE0000000002",
Name: "已停用角色",
Status: domain.RecordInactive,
}
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE0000000002").Return(role, nil)
},
wantErr: true,
},
{
name: "使用者已有角色",
req: usecase.AssignRoleRequest{
UserUID: "user999",
RoleUID: "ROLE0000000001",
},
mockSetup: func() {
role := &entity.Role{
ID: bson.NewObjectID(),
UID: "ROLE0000000001",
Name: "管理員",
Status: domain.RecordActive,
}
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE0000000001").Return(role, nil)
mockUserRoleRepo.EXPECT().Exists(ctx, "user999").Return(true, nil)
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockSetup()
_, err := uc.Assign(ctx, tt.req)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestUserRoleUseCase_Update(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockUserRoleRepo := mockRepo.NewMockUserRoleRepository(mockCtrl)
mockRoleRepo := mockRepo.NewMockRoleRepository(mockCtrl)
uc := NewUserRoleUseCase(UserRoleUseCaseParam{
UserRoleRepo: mockUserRoleRepo,
RoleRepo: mockRoleRepo,
})
ctx := context.Background()
tests := []struct {
name string
userUID string
newRoleID string
mockSetup func()
wantErr bool
}{
{
name: "成功更新角色",
userUID: "user123",
newRoleID: "ROLE0000000002",
mockSetup: func() {
role := &entity.Role{
ID: bson.NewObjectID(),
UID: "ROLE0000000002",
Name: "新角色",
Status: domain.RecordActive,
}
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE0000000002").Return(role, nil)
updatedUserRole := &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000002",
Status: domain.RecordActive,
}
mockUserRoleRepo.EXPECT().Update(ctx, "user123", "ROLE0000000002").Return(updatedUserRole, nil)
},
wantErr: false,
},
{
name: "新角色不存在",
userUID: "user456",
newRoleID: "ROLE9999999999",
mockSetup: func() {
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE9999999999").Return(nil, errors.New("not found"))
},
wantErr: true,
},
{
name: "新角色未啟用",
userUID: "user789",
newRoleID: "ROLE0000000003",
mockSetup: func() {
role := &entity.Role{
ID: bson.NewObjectID(),
UID: "ROLE0000000003",
Name: "已停用角色",
Status: domain.RecordInactive,
}
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE0000000003").Return(role, nil)
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockSetup()
result, err := uc.Update(ctx, tt.userUID, tt.newRoleID)
if tt.wantErr {
assert.Error(t, err)
assert.Nil(t, result)
} else {
assert.NoError(t, err)
assert.NotNil(t, result)
}
})
}
}
func TestUserRoleUseCase_Remove(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockUserRoleRepo := mockRepo.NewMockUserRoleRepository(mockCtrl)
mockRoleRepo := mockRepo.NewMockRoleRepository(mockCtrl)
uc := NewUserRoleUseCase(UserRoleUseCaseParam{
UserRoleRepo: mockUserRoleRepo,
RoleRepo: mockRoleRepo,
})
ctx := context.Background()
tests := []struct {
name string
userUID string
mockSetup func()
wantErr bool
}{
{
name: "成功移除角色",
userUID: "user123",
mockSetup: func() {
mockUserRoleRepo.EXPECT().Delete(ctx, "user123").Return(nil)
},
wantErr: false,
},
{
name: "移除失敗",
userUID: "user456",
mockSetup: func() {
mockUserRoleRepo.EXPECT().Delete(ctx, "user456").Return(errors.New("db error"))
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockSetup()
err := uc.Remove(ctx, tt.userUID)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestUserRoleUseCase_Get(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockUserRoleRepo := mockRepo.NewMockUserRoleRepository(mockCtrl)
mockRoleRepo := mockRepo.NewMockRoleRepository(mockCtrl)
uc := NewUserRoleUseCase(UserRoleUseCaseParam{
UserRoleRepo: mockUserRoleRepo,
RoleRepo: mockRoleRepo,
})
ctx := context.Background()
tests := []struct {
name string
userUID string
mockSetup func()
wantNil bool
wantErr bool
}{
{
name: "成功獲取使用者角色",
userUID: "user123",
mockSetup: func() {
userRole := &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
}
mockUserRoleRepo.EXPECT().Get(ctx, "user123").Return(userRole, nil)
},
wantNil: false,
wantErr: false,
},
{
name: "使用者無角色",
userUID: "user456",
mockSetup: func() {
mockUserRoleRepo.EXPECT().Get(ctx, "user456").Return(nil, errors.New("not found"))
},
wantNil: true,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockSetup()
result, err := uc.Get(ctx, tt.userUID)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
if tt.wantNil {
assert.Nil(t, result)
} else {
assert.NotNil(t, result)
}
})
}
}
func TestUserRoleUseCase_GetByRole(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockUserRoleRepo := mockRepo.NewMockUserRoleRepository(mockCtrl)
mockRoleRepo := mockRepo.NewMockRoleRepository(mockCtrl)
uc := NewUserRoleUseCase(UserRoleUseCaseParam{
UserRoleRepo: mockUserRoleRepo,
RoleRepo: mockRoleRepo,
})
ctx := context.Background()
tests := []struct {
name string
roleUID string
mockSetup func()
wantCount int
wantErr bool
}{
{
name: "成功獲取角色的所有使用者",
roleUID: "ROLE0000000001",
mockSetup: func() {
role := &entity.Role{
ID: bson.NewObjectID(),
UID: "ROLE0000000001",
Name: "管理員",
Status: domain.RecordActive,
}
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE0000000001").Return(role, nil)
userRoles := []*entity.UserRole{
{ID: bson.NewObjectID(), UID: "user1", RoleID: "ROLE0000000001"},
{ID: bson.NewObjectID(), UID: "user2", RoleID: "ROLE0000000001"},
}
mockUserRoleRepo.EXPECT().GetByRoleID(ctx, gomock.Any()).Return(userRoles, nil)
},
wantCount: 2,
wantErr: false,
},
{
name: "角色不存在",
roleUID: "ROLE9999999999",
mockSetup: func() {
mockRoleRepo.EXPECT().GetByUID(ctx, "ROLE9999999999").Return(nil, errors.New("not found"))
},
wantCount: 0,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockSetup()
result, err := uc.GetByRole(ctx, tt.roleUID)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Len(t, result, tt.wantCount)
}
})
}
}
func TestUserRoleUseCase_List(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockUserRoleRepo := mockRepo.NewMockUserRoleRepository(mockCtrl)
mockRoleRepo := mockRepo.NewMockRoleRepository(mockCtrl)
uc := NewUserRoleUseCase(UserRoleUseCaseParam{
UserRoleRepo: mockUserRoleRepo,
RoleRepo: mockRoleRepo,
})
ctx := context.Background()
tests := []struct {
name string
filter usecase.UserRoleFilterRequest
mockSetup func()
wantCount int
wantErr bool
}{
{
name: "成功列出所有使用者角色",
filter: usecase.UserRoleFilterRequest{
Brand: "brand1",
},
mockSetup: func() {
userRoles := []*entity.UserRole{
{ID: bson.NewObjectID(), UID: "user1", RoleID: "ROLE0000000001", Brand: "brand1"},
{ID: bson.NewObjectID(), UID: "user2", RoleID: "ROLE0000000002", Brand: "brand1"},
}
mockUserRoleRepo.EXPECT().List(ctx, gomock.Any()).Return(userRoles, nil)
},
wantCount: 2,
wantErr: false,
},
{
name: "沒有使用者角色",
filter: usecase.UserRoleFilterRequest{
Brand: "unknown",
},
mockSetup: func() {
mockUserRoleRepo.EXPECT().List(ctx, gomock.Any()).Return([]*entity.UserRole{}, nil)
},
wantCount: 0,
wantErr: false,
},
{
name: "Repository 錯誤",
filter: usecase.UserRoleFilterRequest{
Brand: "brand1",
},
mockSetup: func() {
mockUserRoleRepo.EXPECT().List(ctx, gomock.Any()).Return(nil, errors.New("db error"))
},
wantCount: 0,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.mockSetup()
result, err := uc.List(ctx, tt.filter)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Len(t, result, tt.wantCount)
}
})
}
}