package handler_test import ( "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/user-management-system/internal/api/handler" "github.com/user-management-system/internal/domain" "github.com/user-management-system/internal/repository" "github.com/user-management-system/internal/service" gormsqlite "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) // ============================================================================= // Stats Handler Tests - TDD approach // ============================================================================= func setupStatsTestEnv(t *testing.T) (*handler.StatsHandler, *gorm.DB) { t.Helper() gin.SetMode(gin.TestMode) db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{ DriverName: "sqlite", DSN: "file:stats_test?mode=memory&cache=shared", }), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) if err != nil { t.Fatalf("failed to connect database: %v", err) } if err := db.AutoMigrate(&domain.User{}, &domain.Role{}, &domain.LoginLog{}); err != nil { t.Fatalf("failed to migrate: %v", err) } userRepo := repository.NewUserRepository(db) loginLogRepo := repository.NewLoginLogRepository(db) statsSvc := service.NewStatsService(userRepo, loginLogRepo) return handler.NewStatsHandler(statsSvc), db } func TestStatsHandler_GetDashboard(t *testing.T) { h, db := setupStatsTestEnv(t) // 创建测试用户 db.Create(&domain.User{Username: "user1", Status: domain.UserStatusActive}) db.Create(&domain.User{Username: "user2", Status: domain.UserStatusInactive}) t.Run("获取仪表盘统计成功", func(t *testing.T) { w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest("GET", "/api/v1/admin/stats/dashboard", nil) h.GetDashboard(c) if w.Code != http.StatusOK { t.Errorf("期望状态码 %d, 得到 %d", http.StatusOK, w.Code) } var resp map[string]interface{} if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { t.Fatalf("解析响应失败: %v", err) } if resp["code"].(float64) != 0 { t.Errorf("期望 code=0, 得到 %v", resp["code"]) } // data 可能是 map 或 nil if resp["data"] != nil { data := resp["data"].(map[string]interface{}) if data["total_users"] == nil { t.Log("total_users 为空,但响应成功") } } }) } func TestStatsHandler_GetUserStats(t *testing.T) { h, db := setupStatsTestEnv(t) // 创建不同状态的用户 db.Create(&domain.User{Username: "active_user", Status: domain.UserStatusActive}) db.Create(&domain.User{Username: "inactive_user", Status: domain.UserStatusInactive}) db.Create(&domain.User{Username: "locked_user", Status: domain.UserStatusLocked}) t.Run("获取用户统计成功", func(t *testing.T) { w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest("GET", "/api/v1/admin/stats/users", nil) h.GetUserStats(c) if w.Code != http.StatusOK { t.Errorf("期望状态码 %d, 得到 %d", http.StatusOK, w.Code) } var resp map[string]interface{} if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { t.Fatalf("解析响应失败: %v", err) } if resp["code"].(float64) != 0 { t.Errorf("期望 code=0, 得到 %v", resp["code"]) } }) }