463 lines
9.6 KiB
Go
463 lines
9.6 KiB
Go
package repository
|
|
|
|
import (
|
|
"backend/pkg/permission/domain"
|
|
"backend/pkg/permission/domain/entity"
|
|
domainRepo "backend/pkg/permission/domain/repository"
|
|
"context"
|
|
"fmt"
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
|
|
mgo "backend/pkg/library/mongo"
|
|
)
|
|
|
|
func setupRoleRepo(db string) (domainRepo.RoleRepository, func(), error) {
|
|
h, p, tearDown, err := startMongoContainer()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
s, _ := miniredis.Run()
|
|
|
|
conf := &mgo.Conf{
|
|
Schema: mongoSchema,
|
|
Host: fmt.Sprintf("%s:%s", h, p),
|
|
Database: db,
|
|
MaxStaleness: 300,
|
|
MaxPoolSize: 100,
|
|
MinPoolSize: 100,
|
|
MaxConnIdleTime: 300,
|
|
Compressors: []string{},
|
|
EnableStandardReadWriteSplitMode: false,
|
|
ConnectTimeoutMs: 3000,
|
|
}
|
|
|
|
cacheConf := cache.CacheConf{
|
|
cache.NodeConf{
|
|
RedisConf: redis.RedisConf{
|
|
Host: s.Addr(),
|
|
Type: redis.NodeType,
|
|
},
|
|
Weight: 100,
|
|
},
|
|
}
|
|
|
|
cacheOpts := []cache.Option{
|
|
cache.WithExpiry(1000 * time.Microsecond),
|
|
cache.WithNotFoundExpiry(1000 * time.Microsecond),
|
|
}
|
|
|
|
param := RoleRepositoryParam{
|
|
Conf: conf,
|
|
CacheConf: cacheConf,
|
|
CacheOpts: cacheOpts,
|
|
}
|
|
repo := NewRoleRepository(param)
|
|
_, _ = repo.Index20251009002UP(context.Background())
|
|
|
|
return repo, tearDown, nil
|
|
}
|
|
|
|
func TestRoleRepository_CreateAndGet(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
tests := []struct {
|
|
name string
|
|
role *entity.Role
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "成功創建角色",
|
|
role: &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000001",
|
|
ClientID: 1,
|
|
Name: "管理員",
|
|
Status: domain.RecordActive,
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "創建另一個角色",
|
|
role: &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000002",
|
|
ClientID: 1,
|
|
Name: "一般使用者",
|
|
Status: domain.RecordActive,
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := repo.Create(ctx, tt.role)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
|
|
// 驗證可以找到創建的角色
|
|
retrieved, err := repo.GetByUID(ctx, tt.role.UID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.role.UID, retrieved.UID)
|
|
assert.Equal(t, tt.role.Name, retrieved.Name)
|
|
assert.Equal(t, tt.role.ClientID, retrieved.ClientID)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRoleRepository_GetByUID(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testRole := &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000001",
|
|
ClientID: 1,
|
|
Name: "測試角色",
|
|
Status: domain.RecordActive,
|
|
}
|
|
err = repo.Create(ctx, testRole)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
uid string
|
|
wantErr error
|
|
check func(*testing.T, *entity.Role)
|
|
}{
|
|
{
|
|
name: "找到存在的角色",
|
|
uid: "ROLE0000000001",
|
|
wantErr: nil,
|
|
check: func(t *testing.T, role *entity.Role) {
|
|
assert.Equal(t, "測試角色", role.Name)
|
|
assert.Equal(t, 1, role.ClientID)
|
|
},
|
|
},
|
|
{
|
|
name: "不存在的角色",
|
|
uid: "ROLE9999999999",
|
|
wantErr: ErrNotFound,
|
|
check: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
role, err := repo.GetByUID(ctx, tt.uid)
|
|
|
|
if tt.wantErr != nil {
|
|
assert.ErrorIs(t, err, tt.wantErr)
|
|
assert.Nil(t, role)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, role)
|
|
if tt.check != nil {
|
|
tt.check(t, role)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRoleRepository_Update(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testRole := &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000001",
|
|
ClientID: 1,
|
|
Name: "原始名稱",
|
|
Status: domain.RecordActive,
|
|
}
|
|
err = repo.Create(ctx, testRole)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
update func(*entity.Role)
|
|
wantErr bool
|
|
check func(*testing.T, *entity.Role)
|
|
}{
|
|
{
|
|
name: "更新角色名稱",
|
|
update: func(role *entity.Role) {
|
|
role.Name = "新的名稱"
|
|
},
|
|
wantErr: false,
|
|
check: func(t *testing.T, role *entity.Role) {
|
|
assert.Equal(t, "新的名稱", role.Name)
|
|
},
|
|
},
|
|
{
|
|
name: "更新角色狀態",
|
|
update: func(role *entity.Role) {
|
|
role.Status = domain.RecordInactive
|
|
},
|
|
wantErr: false,
|
|
check: func(t *testing.T, role *entity.Role) {
|
|
assert.Equal(t, domain.RecordInactive, role.Status)
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// 獲取當前角色
|
|
role, err := repo.GetByUID(ctx, testRole.UID)
|
|
require.NoError(t, err)
|
|
|
|
// 應用更新
|
|
tt.update(role)
|
|
|
|
// 執行更新
|
|
err = repo.Update(ctx, role)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
|
|
// 驗證更新
|
|
updated, err := repo.GetByUID(ctx, testRole.UID)
|
|
assert.NoError(t, err)
|
|
if tt.check != nil {
|
|
tt.check(t, updated)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRoleRepository_Delete(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testRole := &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000001",
|
|
ClientID: 1,
|
|
Name: "要刪除的角色",
|
|
Status: domain.RecordActive,
|
|
}
|
|
err = repo.Create(ctx, testRole)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("軟刪除角色", func(t *testing.T) {
|
|
err := repo.Delete(ctx, testRole.UID)
|
|
assert.NoError(t, err)
|
|
|
|
// 驗證角色狀態變為已刪除
|
|
role, err := repo.GetByUID(ctx, testRole.UID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, domain.RecordDeleted, role.Status)
|
|
})
|
|
}
|
|
|
|
func TestRoleRepository_List(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testRoles := []*entity.Role{
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000001",
|
|
ClientID: 1,
|
|
Name: "管理員",
|
|
Status: domain.RecordActive,
|
|
},
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000002",
|
|
ClientID: 1,
|
|
Name: "編輯者",
|
|
Status: domain.RecordActive,
|
|
},
|
|
{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000003",
|
|
ClientID: 2,
|
|
Name: "訪客",
|
|
Status: domain.RecordInactive,
|
|
},
|
|
}
|
|
|
|
for _, role := range testRoles {
|
|
err := repo.Create(ctx, role)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
filter domainRepo.RoleFilter
|
|
wantCount int
|
|
}{
|
|
{
|
|
name: "列出所有角色",
|
|
filter: domainRepo.RoleFilter{},
|
|
wantCount: 3,
|
|
},
|
|
{
|
|
name: "按 ClientID 過濾",
|
|
filter: domainRepo.RoleFilter{
|
|
ClientID: 1,
|
|
},
|
|
wantCount: 2,
|
|
},
|
|
{
|
|
name: "按名稱模糊搜尋",
|
|
filter: domainRepo.RoleFilter{
|
|
Name: "管理",
|
|
},
|
|
wantCount: 1,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
roles, err := repo.List(ctx, tt.filter)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Len(t, roles, tt.wantCount)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRoleRepository_Page(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據 - 創建 15 個角色
|
|
for i := 1; i <= 15; i++ {
|
|
role := &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: bson.NewObjectID().Hex(),
|
|
ClientID: 1,
|
|
Name: bson.NewObjectID().Hex(),
|
|
Status: domain.RecordActive,
|
|
}
|
|
err := repo.Create(ctx, role)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
page int
|
|
size int
|
|
wantCount int
|
|
wantTotal int64
|
|
}{
|
|
{
|
|
name: "第一頁,每頁 10 筆",
|
|
page: 1,
|
|
size: 10,
|
|
wantCount: 10,
|
|
wantTotal: 15,
|
|
},
|
|
{
|
|
name: "第二頁,每頁 10 筆",
|
|
page: 2,
|
|
size: 10,
|
|
wantCount: 5,
|
|
wantTotal: 15,
|
|
},
|
|
{
|
|
name: "第一頁,每頁 5 筆",
|
|
page: 1,
|
|
size: 5,
|
|
wantCount: 5,
|
|
wantTotal: 15,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
roles, total, err := repo.Page(ctx, domainRepo.RoleFilter{}, tt.page, tt.size)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Len(t, roles, tt.wantCount)
|
|
assert.Equal(t, tt.wantTotal, total)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRoleRepository_Exists(t *testing.T) {
|
|
repo, tearDown, err := setupRoleRepo("testDB")
|
|
defer tearDown()
|
|
assert.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
// 準備測試數據
|
|
testRole := &entity.Role{
|
|
ID: bson.NewObjectID(),
|
|
UID: "ROLE0000000001",
|
|
ClientID: 1,
|
|
Name: "測試角色",
|
|
Status: domain.RecordActive,
|
|
}
|
|
err = repo.Create(ctx, testRole)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
uid string
|
|
exists bool
|
|
}{
|
|
{
|
|
name: "存在的角色",
|
|
uid: "ROLE0000000001",
|
|
exists: true,
|
|
},
|
|
{
|
|
name: "不存在的角色",
|
|
uid: "ROLE9999999999",
|
|
exists: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
exists, err := repo.Exists(ctx, tt.uid)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.exists, exists)
|
|
})
|
|
}
|
|
}
|