You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

269 lines
6.3 KiB

package model
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// setupMenuTestDB 创建菜单测试数据库(使用MySQL)
func setupMenuTestDB(t *testing.T) *gorm.DB {
t.Helper()
dsn := "root:dev123456@tcp(219.159.132.177:17173)/base?charset=utf8mb4&parseTime=true&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
require.NoError(t, err)
err = db.AutoMigrate(&Menu{})
require.NoError(t, err)
// 清理所有数据确保测试隔离(运行后需重启后端以恢复种子数据)
db.Exec("SET FOREIGN_KEY_CHECKS = 0")
db.Exec("TRUNCATE TABLE menu")
db.Exec("SET FOREIGN_KEY_CHECKS = 1")
return db
}
// createTestMenu 创建测试菜单
func createTestMenu(t *testing.T, db *gorm.DB) *Menu {
t.Helper()
now := time.Now()
menu := &Menu{
Name: "测试菜单",
Path: "/test",
Icon: "Star",
Type: "config",
SortOrder: 1,
Visible: true,
Status: 1,
CreatedAt: now,
UpdatedAt: now,
}
err := db.Create(menu).Error
require.NoError(t, err)
return menu
}
// TestMenuInsert 测试插入菜单
func TestMenuInsert(t *testing.T) {
db := setupMenuTestDB(t)
ctx := context.Background()
menu := &Menu{
Name: "新菜单",
Path: "/new",
Icon: "Plus",
Type: "config",
SortOrder: 5,
Visible: true,
Status: 1,
}
id, err := MenuInsert(ctx, db, menu)
require.NoError(t, err)
assert.Greater(t, id, int64(0))
assert.Equal(t, id, menu.Id)
// 验证数据已保存
saved, err := MenuFindOne(ctx, db, id)
require.NoError(t, err)
assert.Equal(t, "新菜单", saved.Name)
assert.Equal(t, "/new", saved.Path)
assert.Equal(t, "Plus", saved.Icon)
assert.Equal(t, 5, saved.SortOrder)
}
// TestMenuFindOne 测试根据ID查询菜单
func TestMenuFindOne(t *testing.T) {
db := setupMenuTestDB(t)
menu := createTestMenu(t, db)
ctx := context.Background()
found, err := MenuFindOne(ctx, db, menu.Id)
require.NoError(t, err)
require.NotNil(t, found)
assert.Equal(t, menu.Id, found.Id)
assert.Equal(t, "测试菜单", found.Name)
assert.Equal(t, "/test", found.Path)
assert.Equal(t, "Star", found.Icon)
}
// TestMenuFindOne_NotFound 测试查询不存在的菜单
func TestMenuFindOne_NotFound(t *testing.T) {
db := setupMenuTestDB(t)
ctx := context.Background()
found, err := MenuFindOne(ctx, db, 99999)
require.Error(t, err)
require.Nil(t, found)
assert.Equal(t, ErrNotFound, err)
}
// TestMenuFindAll 测试查询所有启用的菜单
func TestMenuFindAll(t *testing.T) {
db := setupMenuTestDB(t)
ctx := context.Background()
// 创建3个菜单:2个启用,1个禁用
now := time.Now()
menus := []Menu{
{Name: "菜单A", Path: "/a", SortOrder: 2, Status: 1, CreatedAt: now, UpdatedAt: now},
{Name: "菜单B", Path: "/b", SortOrder: 1, Status: 1, CreatedAt: now, UpdatedAt: now},
{Name: "菜单C", Path: "/c", SortOrder: 3, Status: 1, CreatedAt: now, UpdatedAt: now},
}
for i := range menus {
err := db.Create(&menus[i]).Error
require.NoError(t, err)
}
// 将菜单C设为禁用(status=0是零值,GORM Create时会使用default:1,需要单独更新)
db.Model(&menus[2]).Update("status", 0)
// 查询所有启用的菜单
result, err := MenuFindAll(ctx, db)
require.NoError(t, err)
assert.Len(t, result, 2)
// 验证按 sort_order 排序
assert.Equal(t, "菜单B", result[0].Name) // sort_order=1
assert.Equal(t, "菜单A", result[1].Name) // sort_order=2
}
// TestMenuFindByIds 测试根据ID列表查询菜单
func TestMenuFindByIds(t *testing.T) {
db := setupMenuTestDB(t)
ctx := context.Background()
// 创建3个菜单
now := time.Now()
menus := []Menu{
{Name: "菜单1", Path: "/1", SortOrder: 1, Status: 1, CreatedAt: now, UpdatedAt: now},
{Name: "菜单2", Path: "/2", SortOrder: 2, Status: 1, CreatedAt: now, UpdatedAt: now},
{Name: "菜单3", Path: "/3", SortOrder: 3, Status: 1, CreatedAt: now, UpdatedAt: now},
}
for i := range menus {
err := db.Create(&menus[i]).Error
require.NoError(t, err)
}
// 查询其中2个
ids := []int64{menus[0].Id, menus[2].Id}
result, err := MenuFindByIds(ctx, db, ids)
require.NoError(t, err)
assert.Len(t, result, 2)
assert.Equal(t, "菜单1", result[0].Name)
assert.Equal(t, "菜单3", result[1].Name)
}
// TestMenuUpdate 测试更新菜单
func TestMenuUpdate(t *testing.T) {
db := setupMenuTestDB(t)
menu := createTestMenu(t, db)
ctx := context.Background()
// 修改菜单数据
menu.Name = "更新后的菜单"
menu.Path = "/updated"
err := MenuUpdate(ctx, db, menu)
require.NoError(t, err)
// 验证更新结果
updated, err := MenuFindOne(ctx, db, menu.Id)
require.NoError(t, err)
assert.Equal(t, "更新后的菜单", updated.Name)
assert.Equal(t, "/updated", updated.Path)
}
// TestMenuDelete 测试删除菜单
func TestMenuDelete(t *testing.T) {
db := setupMenuTestDB(t)
menu := createTestMenu(t, db)
menuId := menu.Id
ctx := context.Background()
err := MenuDelete(ctx, db, menuId)
require.NoError(t, err)
// 验证菜单已被删除
_, err = MenuFindOne(ctx, db, menuId)
require.Error(t, err)
assert.Equal(t, ErrNotFound, err)
}
// TestMenuHasChildren 测试检查菜单是否有子菜单
func TestMenuHasChildren(t *testing.T) {
db := setupMenuTestDB(t)
ctx := context.Background()
now := time.Now()
// 创建父菜单
parent := &Menu{
Name: "父菜单",
Path: "/parent",
SortOrder: 1,
Status: 1,
CreatedAt: now,
UpdatedAt: now,
}
err := db.Create(parent).Error
require.NoError(t, err)
// 创建子菜单
child := &Menu{
ParentId: parent.Id,
Name: "子菜单",
Path: "/parent/child",
SortOrder: 1,
Status: 1,
CreatedAt: now,
UpdatedAt: now,
}
err = db.Create(child).Error
require.NoError(t, err)
// 创建无子菜单的孤立菜单
orphan := &Menu{
Name: "孤立菜单",
Path: "/orphan",
SortOrder: 1,
Status: 1,
CreatedAt: now,
UpdatedAt: now,
}
err = db.Create(orphan).Error
require.NoError(t, err)
// 验证父菜单有子菜单
hasChildren, err := MenuHasChildren(ctx, db, parent.Id)
require.NoError(t, err)
assert.True(t, hasChildren)
// 验证孤立菜单没有子菜单
hasChildren, err = MenuHasChildren(ctx, db, orphan.Id)
require.NoError(t, err)
assert.False(t, hasChildren)
}