feat(lyra)!: 接入分类查询并集中组装依赖

- 使用 Squirrel 与 sqlx 实现分类查询
- 集中组装依赖并向 handler 注入 model 接口
- 显式转换分类响应 DTO,统一空列表输出
- 补充路由与 handler 测试,同步架构文档

BREAKING CHANGE: 将 GET /hello 替换为 GET /test,响应由问候字符串改为分类列表
This commit is contained in:
2026-10-17 17:06:20 +08:00
parent 8c0c9978e5
commit ab83ad96b4
16 changed files with 546 additions and 89 deletions
+59 -10
View File
@@ -10,19 +10,68 @@ import (
"github.com/gin-gonic/gin"
)
func TestHelloRoute(t *testing.T) {
gin.SetMode(gin.TestMode)
engine := gin.New()
router.RegisterRoutes(engine)
const (
stubStatus = http.StatusAccepted
stubBody = "injected test handler"
)
// newStubHandlers 返回记录调用次数并输出固定状态码与响应体的替身处理器。
func newStubHandlers(calls *int) router.Handlers {
return router.Handlers{
TestHandler: func(c *gin.Context) {
*calls++
c.String(stubStatus, stubBody)
},
}
}
func TestRouteInvokesInjectedHandler(t *testing.T) {
gin.SetMode(gin.TestMode)
var calls int
engine := gin.New()
router.RegisterRoutes(engine, newStubHandlers(&calls))
recorder := httptest.NewRecorder()
engine.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/hello", nil))
engine.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/test", nil))
if recorder.Code != http.StatusOK {
t.Fatalf("GET /hello status = %d, want %d", recorder.Code, http.StatusOK)
if calls != 1 {
t.Fatalf("GET /test 替身调用次数 = %d, want 1", calls)
}
if recorder.Code != stubStatus {
t.Fatalf("GET /test status = %d, want %d", recorder.Code, stubStatus)
}
if got := recorder.Body.String(); got != stubBody {
t.Fatalf("GET /test body = %q, want %q", got, stubBody)
}
want := `{"success":true,"data":"Hello, World!"}`
if got := recorder.Body.String(); got != want {
t.Fatalf("GET /hello body = %q, want %q", got, want)
}
func TestRouteSkipsHandlerForUnknownPathOrMethod(t *testing.T) {
gin.SetMode(gin.TestMode)
tests := []struct {
name string
method string
path string
}{
{name: "未知路径", method: http.MethodGet, path: "/unknown"},
{name: "不支持的方法", method: http.MethodPost, path: "/test"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var calls int
engine := gin.New()
router.RegisterRoutes(engine, newStubHandlers(&calls))
recorder := httptest.NewRecorder()
engine.ServeHTTP(recorder, httptest.NewRequest(tt.method, tt.path, nil))
if calls != 0 {
t.Fatalf("%s %s 替身调用次数 = %d, want 0", tt.method, tt.path, calls)
}
if recorder.Code != http.StatusNotFound {
t.Fatalf("%s %s status = %d, want %d", tt.method, tt.path, recorder.Code, http.StatusNotFound)
}
})
}
}