项目文件夹

文件
2026-07-14 10:24:10 +08:00

460 行
11 KiB
Go

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
package router_test
import (
"net/http/httptest"
"testing"
"github.com/EthanCodeCraft/xlgo-core/router"
"github.com/gin-gonic/gin"
)
func setupTestRouter() *gin.Engine {
gin.SetMode(gin.TestMode)
return gin.New()
}
func TestNewRegistry(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
if registry == nil {
t.Error("NewRegistry should not return nil")
}
}
func TestRegistryUse(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
result := registry.Use(func(c *gin.Context) { c.Next() })
if result == nil {
t.Error("Use should return registry for chaining")
}
}
func TestRegisterModule(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
module := &testModule{name: "test"}
result := registry.RegisterModule(module)
if result == nil {
t.Error("RegisterModule should return registry for chaining")
}
}
func TestRegisterModuleFunc(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
result := registry.RegisterModuleFunc("test", func(r *gin.RouterGroup) {
r.GET("/test", func(c *gin.Context) { c.JSON(200, gin.H{}) })
})
if result == nil {
t.Error("RegisterModuleFunc should return registry for chaining")
}
}
func TestNewVersion(t *testing.T) {
v := router.NewVersion("v1", "/api/v1")
if v.Version != "v1" {
t.Errorf("Version = %s, want v1", v.Version)
}
if v.BasePath != "/api/v1" {
t.Errorf("BasePath = %s, want /api/v1", v.BasePath)
}
}
func TestVersionAddModule(t *testing.T) {
v := router.NewVersion("v1", "/api/v1")
module := &testModule{name: "user"}
result := v.AddModule(module)
if result == nil {
t.Error("AddModule should return VersionedAPI for chaining")
}
}
func TestVersionAddModuleFunc(t *testing.T) {
v := router.NewVersion("v1", "/api/v1")
result := v.AddModuleFunc("user", func(r *gin.RouterGroup) {
r.GET("/users", func(c *gin.Context) {})
})
if result == nil {
t.Error("AddModuleFunc should return VersionedAPI for chaining")
}
}
func TestRegisterVersion(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
v := router.NewVersion("v1", "/api/v1")
result := registry.RegisterVersion(v)
if result == nil {
t.Error("RegisterVersion should return registry for chaining")
}
}
func TestNewMiddlewareGroup(t *testing.T) {
group := router.NewMiddlewareGroup("auth", func(c *gin.Context) { c.Next() })
if group.Name != "auth" {
t.Errorf("Name = %s, want auth", group.Name)
}
if len(group.Middlewares) != 1 {
t.Errorf("Middlewares length = %d, want 1", len(group.Middlewares))
}
}
func TestRegisterMiddlewareGroup(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
group := router.NewMiddlewareGroup("auth")
result := registry.RegisterMiddlewareGroup(group)
if result == nil {
t.Error("RegisterMiddlewareGroup should return registry for chaining")
}
}
func TestGetMiddlewareGroup(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
middleware := func(c *gin.Context) { c.Next() }
group := router.NewMiddlewareGroup("auth", middleware)
registry.RegisterMiddlewareGroup(group)
mws := registry.GetMiddlewareGroup("auth")
if len(mws) != 1 {
t.Errorf("GetMiddlewareGroup length = %d, want 1", len(mws))
}
// 不存在的分组
mws2 := registry.GetMiddlewareGroup("nonexistent")
if mws2 != nil {
t.Error("GetMiddlewareGroup nonexistent should return nil")
}
}
func TestApply(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
registry.RegisterModuleFunc("test", func(r *gin.RouterGroup) {
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "hello"})
})
})
registry.Apply()
// 测试路由是否生效
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/hello", nil)
engine.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Apply route status = %d, want 200", w.Code)
}
}
func TestApplyWithVersion(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
v1 := router.NewVersion("v1", "/api/v1")
v1.AddModuleFunc("user", func(r *gin.RouterGroup) {
r.GET("/users", func(c *gin.Context) {
c.JSON(200, gin.H{"version": "v1"})
})
})
registry.RegisterVersion(v1)
registry.Apply()
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/users", nil)
engine.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Versioned route status = %d, want 200", w.Code)
}
}
func TestApplyWithMiddleware(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
// 全局中间件
registry.Use(func(c *gin.Context) {
c.Set("global", true)
c.Next()
})
registry.RegisterModuleFunc("test", func(r *gin.RouterGroup) {
r.GET("/test", func(c *gin.Context) {
val, _ := c.Get("global")
c.JSON(200, gin.H{"global": val})
})
})
registry.Apply()
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
engine.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Middleware route status = %d", w.Code)
}
}
func TestVersionMiddleware(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
v1 := router.NewVersion("v1", "/api/v1", func(c *gin.Context) {
c.Set("version", "v1")
c.Next()
})
v1.AddModuleFunc("user", func(r *gin.RouterGroup) {
r.GET("/users", func(c *gin.Context) {
val, _ := c.Get("version")
c.JSON(200, gin.H{"version": val})
})
})
registry.RegisterVersion(v1)
registry.Apply()
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/users", nil)
engine.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Version middleware route status = %d", w.Code)
}
}
func TestMultipleVersions(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
v1 := router.NewVersion("v1", "/api/v1")
v1.AddModuleFunc("user", func(r *gin.RouterGroup) {
r.GET("/users", func(c *gin.Context) { c.JSON(200, gin.H{"version": "v1"}) })
})
v2 := router.NewVersion("v2", "/api/v2")
v2.AddModuleFunc("user", func(r *gin.RouterGroup) {
r.GET("/users", func(c *gin.Context) { c.JSON(200, gin.H{"version": "v2"}) })
})
registry.RegisterVersion(v1)
registry.RegisterVersion(v2)
registry.Apply()
// 测试 v1
w1 := httptest.NewRecorder()
req1 := httptest.NewRequest("GET", "/api/v1/users", nil)
engine.ServeHTTP(w1, req1)
// 测试 v2
w2 := httptest.NewRecorder()
req2 := httptest.NewRequest("GET", "/api/v2/users", nil)
engine.ServeHTTP(w2, req2)
if w1.Code != 200 || w2.Code != 200 {
t.Error("Multiple versions should both work")
}
}
func TestInitAndGetRegistry(t *testing.T) {
engine := setupTestRouter()
registry := router.Init(engine)
if registry == nil {
t.Error("Init should return registry")
}
registry2 := router.GetRegistry()
if registry2 != registry {
t.Error("GetRegistry should return same registry")
}
}
func TestGlobalFunctions(t *testing.T) {
engine := setupTestRouter()
router.Init(engine)
router.Use(func(c *gin.Context) { c.Next() })
router.RegisterModule(&testModule{name: "test"})
router.RegisterVersion(router.NewVersion("v1", "/api/v1"))
registry := router.GetRegistry()
if registry == nil {
t.Error("Global functions should work")
}
}
func TestGlobalApply(t *testing.T) {
engine := setupTestRouter()
router.Init(engine)
router.RegisterModuleFunc("hello", func(r *gin.RouterGroup) {
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "hello"})
})
})
router.Apply()
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/hello", nil)
engine.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("Global Apply status = %d, want 200", w.Code)
}
}
func TestModuleFunc(t *testing.T) {
var mf router.ModuleFunc = func(r *gin.RouterGroup) {
r.GET("/test", func(c *gin.Context) {})
}
// 验证实现了 Module 接口
var _ router.Module = mf
}
func TestRESTfulRoute(t *testing.T) {
engine := setupTestRouter()
group := engine.Group("/api")
rest := router.NewRESTful(group, "/users")
rest.GET(func(c *gin.Context) { c.JSON(200, gin.H{}) })
rest.POST(func(c *gin.Context) { c.JSON(201, gin.H{}) })
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/users", nil)
engine.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("RESTful GET status = %d", w.Code)
}
}
func TestRESTfulCRUD(t *testing.T) {
engine := setupTestRouter()
group := engine.Group("/api")
rest := router.NewRESTful(group, "/items")
rest.CRUD(
func(c *gin.Context) { c.JSON(200, gin.H{"action": "list"}) },
func(c *gin.Context) { c.JSON(200, gin.H{"action": "detail"}) },
func(c *gin.Context) { c.JSON(201, gin.H{"action": "create"}) },
func(c *gin.Context) { c.JSON(200, gin.H{"action": "update"}) },
func(c *gin.Context) { c.JSON(204, gin.H{}) },
)
tests := []struct {
method string
path string
code int
}{
{"GET", "/api/items", 200},
{"GET", "/api/items/1", 200},
{"POST", "/api/items", 201},
{"PUT", "/api/items/1", 200},
{"DELETE", "/api/items/1", 204},
}
for _, tt := range tests {
w := httptest.NewRecorder()
req := httptest.NewRequest(tt.method, tt.path, nil)
engine.ServeHTTP(w, req)
if w.Code != tt.code {
t.Errorf("%s %s status = %d, want %d", tt.method, tt.path, w.Code, tt.code)
}
}
}
func TestRESTfulPartialCRUD(t *testing.T) {
engine := setupTestRouter()
group := engine.Group("/api")
rest := router.NewRESTful(group, "/items")
// 只注册 list 和 create
rest.CRUD(
func(c *gin.Context) { c.JSON(200, gin.H{}) }, // list
nil, // no detail
func(c *gin.Context) { c.JSON(201, gin.H{}) }, // create
nil, // no update
nil, // no delete
)
// list 存在
w1 := httptest.NewRecorder()
req1 := httptest.NewRequest("GET", "/api/items", nil)
engine.ServeHTTP(w1, req1)
if w1.Code != 200 {
t.Error("Partial CRUD list should work")
}
// detail 不存在(404
w2 := httptest.NewRecorder()
req2 := httptest.NewRequest("GET", "/api/items/1", nil)
engine.ServeHTTP(w2, req2)
if w2.Code != 404 {
t.Errorf("Partial CRUD detail should be 404, got %d", w2.Code)
}
}
func TestGroup(t *testing.T) {
engine := setupTestRouter()
group := router.Group(engine, "/api", func(c *gin.Context) { c.Next() })
if group == nil {
t.Error("Group should not return nil")
}
}
func TestGroupWithMiddlewareGroup(t *testing.T) {
engine := setupTestRouter()
registry := router.NewRegistry(engine)
registry.RegisterMiddlewareGroup(router.NewMiddlewareGroup("auth", func(c *gin.Context) { c.Next() }))
group := registry.GroupWithMiddlewareGroup(engine, "/api", "auth")
if group == nil {
t.Error("GroupWithMiddlewareGroup should not return nil")
}
}
func TestModuleInterface(t *testing.T) {
module := &testModule{name: "test"}
// 测试 Name 方法
if module.Name() != "test" {
t.Error("Module Name failed")
}
// 测试实现了接口
var _ router.Module = module
}
// 测试模块实现
type testModule struct {
name string
}
func (m *testModule) Name() string { return m.name }
func (m *testModule) Register(r *gin.RouterGroup) {
r.GET("/"+m.name, func(c *gin.Context) { c.JSON(200, gin.H{"module": m.name}) })
}