Files
xlgo-core/response/mode_test.go
T
杭州明婳科技 0c9f256dfc feat(v1.1.0): HA & Manager 化
对应体检报告 #10-#24,一次性完成 v1.1.0 全部 13 项:

- #10 storage/cache/redis/jwt/logger 五组件 Manager 化(XxxManager + DefaultXxx + SetDefaultXxxManager,包级 facade 保留兼容)
- #11 删除 wire 包 + 清理 StartServerWithPort/GracefulShutdown 双轨
- #12 Lifecycle Hooks(OnInit/OnStart/OnReady/OnStop)
- #13 Server 参数配置化(timeout/TLS/unix_socket/response_mode)
- #14 JWTConfig.Expire 改 time.Duration + 删 AppConfig.TokenExpire
- #15 response Mode 开关(ModeBusiness/ModeREST)
- #16 Config.Validate 启动期校验
- #17 livez/readyz 探针路由
- #18 Prometheus metrics 中间件 + /metrics
- #19 请求级 Timeout 中间件
- #21 主库探活 + replica 健康剔除
- #22 App.Go + in-flight goroutine 管理
- #24 RequestID 默认装入 + #23 核对

Breaking:删 wire、删 TokenExpire、JWTConfig.Expire 类型变更、删双轨函数。
详见 CHANGELOG 升级说明。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 10:41:05 +08:00

94 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package response_test
import (
"encoding/json"
"net/http/httptest"
"testing"
"github.com/EthanCodeCraft/xlgo-core/response"
"github.com/gin-gonic/gin"
)
// withMode 切换响应模式并在测试结束后恢复为默认 ModeBusiness。
func withMode(t *testing.T, m response.Mode) {
t.Helper()
response.SetMode(m)
t.Cleanup(func() { response.SetMode(response.ModeBusiness) })
}
func TestSetGetMode(t *testing.T) {
withMode(t, response.ModeREST)
if response.GetMode() != response.ModeREST {
t.Errorf("GetMode = %v, want ModeREST", response.GetMode())
}
}
func TestModeBusinessReturns200(t *testing.T) {
withMode(t, response.ModeBusiness)
r := setupTestRouter()
r.GET("/u", func(c *gin.Context) { response.Unauthorized(c, "no") })
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest("GET", "/u", nil))
if w.Code != 200 {
t.Errorf("ModeBusiness Unauthorized status = %d, want 200", w.Code)
}
}
func TestModeRESTMapsStatus(t *testing.T) {
withMode(t, response.ModeREST)
cases := []struct {
path string
fn func(c *gin.Context)
wantCode int
}{
{"/unauth", func(c *gin.Context) { response.Unauthorized(c, "no") }, 401},
{"/notfound", func(c *gin.Context) { response.NotFound(c, "no") }, 404},
{"/server", func(c *gin.Context) { response.ServerError(c, "err") }, 500},
{"/ratelimit", func(c *gin.Context) { response.RateLimit(c) }, 429},
{"/fail", func(c *gin.Context) { response.Fail(c, "bad") }, 200}, // CodeFail 不映射
}
for _, tc := range cases {
r := setupTestRouter()
r.GET(tc.path, tc.fn)
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest("GET", tc.path, nil))
if w.Code != tc.wantCode {
t.Errorf("%s status = %d, want %d", tc.path, w.Code, tc.wantCode)
}
// body 仍带业务码
var body response.Response
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
t.Errorf("%s body unmarshal: %v", tc.path, err)
}
if body.Code == 0 && tc.path != "/fail" {
// 非 Fail 路径 code 应非 0Fail 的 CodeFail=1 也非 0,跳过)
}
}
}
func TestCustomIgnoresMode(t *testing.T) {
withMode(t, response.ModeBusiness) // 即使 business 模式,Custom 也用指定 status
r := setupTestRouter()
r.GET("/c", func(c *gin.Context) { response.Custom(c, 418, 999, "teapot", nil) })
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest("GET", "/c", nil))
if w.Code != 418 {
t.Errorf("Custom status = %d, want 418", w.Code)
}
}
func TestFailWithErrorREST(t *testing.T) {
withMode(t, response.ModeREST)
r := setupTestRouter()
r.GET("/e", func(c *gin.Context) { response.FailWithError(c, response.ErrUnauthorized) })
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest("GET", "/e", nil))
if w.Code != 401 {
t.Errorf("FailWithError(ErrUnauthorized) status = %d, want 401", w.Code)
}
}