lolly/internal/handler/router_test.go
xfy 413e418b37 test: 添加 handler/logging/middleware/server 模块单元测试
- internal/handler/static_test.go: 21 个测试用例覆盖静态文件服务和路径遍历安全
- internal/handler/router_test.go: 9 个测试用例覆盖路由注册和方法区分
- internal/logging/logging_test.go: 7 个测试用例覆盖日志级别解析
- internal/middleware/middleware_test.go: 4 个测试用例覆盖中间件链逆序包装
- internal/server/server_test.go: 5 个测试用例覆盖服务器创建和停止
- internal/server/vhost_test.go: 18 个测试用例覆盖虚拟主机路由

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:21:49 +08:00

231 lines
5.0 KiB
Go

// Package handler 提供路由器的测试。
package handler
import (
"testing"
"github.com/valyala/fasthttp"
)
// TestRouterGET 测试 GET 路由注册。
func TestRouterGET(t *testing.T) {
r := NewRouter()
var called bool
handler := func(ctx *fasthttp.RequestCtx) {
called = true
ctx.WriteString("GET response")
}
r.GET("/test", handler)
// 模拟 GET 请求
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("GET")
ctx.Request.SetRequestURI("/test")
r.Handler()(&ctx)
if !called {
t.Error("GET handler 未被调用")
}
if string(ctx.Response.Body()) != "GET response" {
t.Errorf("响应体 = %q, want %q", string(ctx.Response.Body()), "GET response")
}
}
// TestRouterPOST 测试 POST 路由注册。
func TestRouterPOST(t *testing.T) {
r := NewRouter()
var called bool
handler := func(ctx *fasthttp.RequestCtx) {
called = true
ctx.WriteString("POST response")
}
r.POST("/submit", handler)
// 模拟 POST 请求
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("POST")
ctx.Request.SetRequestURI("/submit")
r.Handler()(&ctx)
if !called {
t.Error("POST handler 未被调用")
}
if string(ctx.Response.Body()) != "POST response" {
t.Errorf("响应体 = %q, want %q", string(ctx.Response.Body()), "POST response")
}
}
// TestRouterMultipleMethods 测试同路径不同方法的区分。
func TestRouterMultipleMethods(t *testing.T) {
r := NewRouter()
var getCalled, postCalled bool
r.GET("/api", func(ctx *fasthttp.RequestCtx) {
getCalled = true
ctx.WriteString("GET api")
})
r.POST("/api", func(ctx *fasthttp.RequestCtx) {
postCalled = true
ctx.WriteString("POST api")
})
// 测试 GET 请求
var getCtx fasthttp.RequestCtx
getCtx.Request.Header.SetMethod("GET")
getCtx.Request.SetRequestURI("/api")
r.Handler()(&getCtx)
if !getCalled {
t.Error("GET handler 未被调用")
}
if postCalled {
t.Error("POST handler 不应被调用")
}
if string(getCtx.Response.Body()) != "GET api" {
t.Errorf("GET 响应体 = %q, want %q", string(getCtx.Response.Body()), "GET api")
}
// 重置并测试 POST 请求
var postCtx fasthttp.RequestCtx
postCtx.Request.Header.SetMethod("POST")
postCtx.Request.SetRequestURI("/api")
r.Handler()(&postCtx)
if !postCalled {
t.Error("POST handler 未被调用")
}
if string(postCtx.Response.Body()) != "POST api" {
t.Errorf("POST 响应体 = %q, want %q", string(postCtx.Response.Body()), "POST api")
}
}
// TestRouterHandlerNotNil 测试 Handler() 返回非 nil。
func TestRouterHandlerNotNil(t *testing.T) {
r := NewRouter()
handler := r.Handler()
if handler == nil {
t.Error("Handler() 返回 nil, want non-nil")
}
}
// TestRouterMultipleRoutes 测试多路由注册。
func TestRouterMultipleRoutes(t *testing.T) {
r := NewRouter()
routes := map[string]string{
"/users": "users handler",
"/products": "products handler",
"/orders": "orders handler",
}
for path, response := range routes {
r.GET(path, func(ctx *fasthttp.RequestCtx) {
ctx.WriteString(response)
})
}
for path, expected := range routes {
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("GET")
ctx.Request.SetRequestURI(path)
r.Handler()(&ctx)
if string(ctx.Response.Body()) != expected {
t.Errorf("路径 %s 响应体 = %q, want %q", path, string(ctx.Response.Body()), expected)
}
}
}
// TestRouterPUT 测试 PUT 路由注册。
func TestRouterPUT(t *testing.T) {
r := NewRouter()
var called bool
r.PUT("/update", func(ctx *fasthttp.RequestCtx) {
called = true
ctx.WriteString("PUT response")
})
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("PUT")
ctx.Request.SetRequestURI("/update")
r.Handler()(&ctx)
if !called {
t.Error("PUT handler 未被调用")
}
}
// TestRouterDELETE 测试 DELETE 路由注册。
func TestRouterDELETE(t *testing.T) {
r := NewRouter()
var called bool
r.DELETE("/remove", func(ctx *fasthttp.RequestCtx) {
called = true
ctx.WriteString("DELETE response")
})
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("DELETE")
ctx.Request.SetRequestURI("/remove")
r.Handler()(&ctx)
if !called {
t.Error("DELETE handler 未被调用")
}
}
// TestRouterHEAD 测试 HEAD 路由注册。
func TestRouterHEAD(t *testing.T) {
r := NewRouter()
var called bool
r.HEAD("/info", func(ctx *fasthttp.RequestCtx) {
called = true
ctx.Response.Header.Set("Content-Length", "100")
})
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("HEAD")
ctx.Request.SetRequestURI("/info")
r.Handler()(&ctx)
if !called {
t.Error("HEAD handler 未被调用")
}
}
// TestRouterNotFound 测试未匹配路由的处理。
func TestRouterNotFound(t *testing.T) {
r := NewRouter()
r.GET("/exists", func(ctx *fasthttp.RequestCtx) {
ctx.WriteString("found")
})
var ctx fasthttp.RequestCtx
ctx.Request.Header.SetMethod("GET")
ctx.Request.SetRequestURI("/notexists")
r.Handler()(&ctx)
if ctx.Response.StatusCode() != fasthttp.StatusNotFound {
t.Errorf("状态码 = %d, want %d", ctx.Response.StatusCode(), fasthttp.StatusNotFound)
}
}