backend/pkg/permission/repository/user_role_test.go

546 lines
12 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 setupUserRoleRepo(db string) (domainRepo.UserRoleRepository, 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 := UserRoleRepositoryParam{
Conf: conf,
CacheConf: cacheConf,
CacheOpts: cacheOpts,
}
repo := NewUserRoleRepository(param)
_, _ = repo.Index20251009004UP(context.Background())
return repo, tearDown, nil
}
func TestUserRoleRepository_CreateAndGet(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
tests := []struct {
name string
userRole *entity.UserRole
wantErr bool
}{
{
name: "成功創建使用者角色",
userRole: &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
},
wantErr: false,
},
{
name: "創建另一個使用者角色",
userRole: &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand2",
UID: "user456",
RoleID: "ROLE0000000002",
Status: domain.RecordActive,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := repo.Create(ctx, tt.userRole)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
// 驗證可以找到創建的使用者角色
retrieved, err := repo.Get(ctx, tt.userRole.UID)
assert.NoError(t, err)
assert.Equal(t, tt.userRole.UID, retrieved.UID)
assert.Equal(t, tt.userRole.RoleID, retrieved.RoleID)
assert.Equal(t, tt.userRole.Brand, retrieved.Brand)
}
})
}
}
func TestUserRoleRepository_Get(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRole := &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
}
err = repo.Create(ctx, testUserRole)
require.NoError(t, err)
tests := []struct {
name string
uid string
wantErr error
check func(*testing.T, *entity.UserRole)
}{
{
name: "找到存在的使用者角色",
uid: "user123",
wantErr: nil,
check: func(t *testing.T, ur *entity.UserRole) {
assert.Equal(t, "ROLE0000000001", ur.RoleID)
assert.Equal(t, "brand1", ur.Brand)
},
},
{
name: "不存在的使用者",
uid: "user999",
wantErr: ErrNotFound,
check: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ur, err := repo.Get(ctx, tt.uid)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
assert.Nil(t, ur)
} else {
assert.NoError(t, err)
assert.NotNil(t, ur)
if tt.check != nil {
tt.check(t, ur)
}
}
})
}
}
func TestUserRoleRepository_Update(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRole := &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
}
err = repo.Create(ctx, testUserRole)
require.NoError(t, err)
tests := []struct {
name string
uid string
newRoleID string
wantErr error
check func(*testing.T, *entity.UserRole)
}{
{
name: "成功更新角色",
uid: "user123",
newRoleID: "ROLE0000000002",
wantErr: nil,
check: func(t *testing.T, ur *entity.UserRole) {
assert.Equal(t, "ROLE0000000002", ur.RoleID)
},
},
{
name: "更新不存在的使用者",
uid: "user999",
newRoleID: "ROLE0000000003",
wantErr: ErrNotFound,
check: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ur, err := repo.Update(ctx, tt.uid, tt.newRoleID)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
assert.Nil(t, ur)
} else {
assert.NoError(t, err)
assert.NotNil(t, ur)
if tt.check != nil {
tt.check(t, ur)
}
// 驗證更新
retrieved, err := repo.Get(ctx, tt.uid)
assert.NoError(t, err)
assert.Equal(t, tt.newRoleID, retrieved.RoleID)
}
})
}
}
func TestUserRoleRepository_Delete(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRole := &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
}
err = repo.Create(ctx, testUserRole)
require.NoError(t, err)
t.Run("刪除使用者角色", func(t *testing.T) {
err := repo.Delete(ctx, testUserRole.UID)
assert.NoError(t, err)
// 驗證已被刪除
_, err = repo.Get(ctx, testUserRole.UID)
assert.ErrorIs(t, err, ErrNotFound)
})
t.Run("刪除不存在的使用者", func(t *testing.T) {
err := repo.Delete(ctx, "user999")
assert.NoError(t, err) // 刪除不存在的記錄不應該報錯
})
}
func TestUserRoleRepository_GetByRoleID(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRoles := []*entity.UserRole{
{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user1",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
},
{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user2",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
},
{
ID: bson.NewObjectID(),
Brand: "brand2",
UID: "user3",
RoleID: "ROLE0000000002",
Status: domain.RecordActive,
},
}
for _, ur := range testUserRoles {
err := repo.Create(ctx, ur)
require.NoError(t, err)
}
tests := []struct {
name string
roleID string
wantCount int
}{
{
name: "找到多個使用者",
roleID: "ROLE0000000001",
wantCount: 2,
},
{
name: "找到單一使用者",
roleID: "ROLE0000000002",
wantCount: 1,
},
{
name: "不存在的角色",
roleID: "ROLE9999999999",
wantCount: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
userRoles, err := repo.GetByRoleID(ctx, tt.roleID)
assert.NoError(t, err)
assert.Len(t, userRoles, tt.wantCount)
for _, ur := range userRoles {
assert.Equal(t, tt.roleID, ur.RoleID)
}
})
}
}
func TestUserRoleRepository_List(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRoles := []*entity.UserRole{
{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user1",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
},
{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user2",
RoleID: "ROLE0000000002",
Status: domain.RecordActive,
},
{
ID: bson.NewObjectID(),
Brand: "brand2",
UID: "user3",
RoleID: "ROLE0000000001",
Status: domain.RecordInactive,
},
}
for _, ur := range testUserRoles {
err := repo.Create(ctx, ur)
require.NoError(t, err)
}
tests := []struct {
name string
filter domainRepo.UserRoleFilter
wantCount int
}{
{
name: "列出所有使用者角色",
filter: domainRepo.UserRoleFilter{},
wantCount: 3,
},
{
name: "按 Brand 過濾",
filter: domainRepo.UserRoleFilter{
Brand: "brand1",
},
wantCount: 2,
},
{
name: "按 RoleID 過濾",
filter: domainRepo.UserRoleFilter{
RoleID: "ROLE0000000001",
},
wantCount: 2,
},
{
name: "組合過濾",
filter: domainRepo.UserRoleFilter{
Brand: "brand1",
RoleID: "ROLE0000000001",
},
wantCount: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
userRoles, err := repo.List(ctx, tt.filter)
assert.NoError(t, err)
assert.Len(t, userRoles, tt.wantCount)
})
}
}
func TestUserRoleRepository_CountByRoleID(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRoles := []*entity.UserRole{
{ID: bson.NewObjectID(), Brand: "brand1", UID: "user1", RoleID: "ROLE0000000001", Status: domain.RecordActive},
{ID: bson.NewObjectID(), Brand: "brand1", UID: "user2", RoleID: "ROLE0000000001", Status: domain.RecordActive},
{ID: bson.NewObjectID(), Brand: "brand1", UID: "user3", RoleID: "ROLE0000000001", Status: domain.RecordActive},
{ID: bson.NewObjectID(), Brand: "brand2", UID: "user4", RoleID: "ROLE0000000002", Status: domain.RecordActive},
{ID: bson.NewObjectID(), Brand: "brand2", UID: "user5", RoleID: "ROLE0000000002", Status: domain.RecordActive},
}
for _, ur := range testUserRoles {
err := repo.Create(ctx, ur)
require.NoError(t, err)
}
tests := []struct {
name string
roleIDs []string
wantCount map[string]int
}{
{
name: "統計多個角色",
roleIDs: []string{"ROLE0000000001", "ROLE0000000002"},
wantCount: map[string]int{
"ROLE0000000001": 3,
"ROLE0000000002": 2,
},
},
{
name: "統計單一角色",
roleIDs: []string{"ROLE0000000001"},
wantCount: map[string]int{
"ROLE0000000001": 3,
},
},
{
name: "統計不存在的角色",
roleIDs: []string{"ROLE9999999999"},
wantCount: map[string]int{
"ROLE9999999999": 0,
},
},
{
name: "混合存在和不存在的角色",
roleIDs: []string{"ROLE0000000001", "ROLE9999999999"},
wantCount: map[string]int{
"ROLE0000000001": 3,
"ROLE9999999999": 0,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
counts, err := repo.CountByRoleID(ctx, tt.roleIDs)
assert.NoError(t, err)
assert.Equal(t, tt.wantCount, counts)
})
}
}
func TestUserRoleRepository_Exists(t *testing.T) {
repo, tearDown, err := setupUserRoleRepo("testDB")
defer tearDown()
assert.NoError(t, err)
ctx := context.Background()
// 準備測試數據
testUserRole := &entity.UserRole{
ID: bson.NewObjectID(),
Brand: "brand1",
UID: "user123",
RoleID: "ROLE0000000001",
Status: domain.RecordActive,
}
err = repo.Create(ctx, testUserRole)
require.NoError(t, err)
tests := []struct {
name string
uid string
exists bool
}{
{
name: "存在的使用者角色",
uid: "user123",
exists: true,
},
{
name: "不存在的使用者",
uid: "user999",
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)
})
}
}