460 lines
11 KiB
Go
460 lines
11 KiB
Go
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}) })
|
||
}
|