package auth_test import ( "bytes" "encoding/json" "fmt" "net/http" "net/http/httptest" "testing" "time" "task-track-backend/internal/config" "task-track-backend/internal/router" "task-track-backend/pkg/database" ) func TestAuthUserFullFlow(t *testing.T) { cfg := config.Load() db, err := database.Init(cfg.Database) if err != nil { t.Fatalf("数据库连接失败: %v", err) } r := router.Setup(db) username := "testuser_api" password := "testpass123" email := "testuser_api@example.com" var userID uint var token string // 注册前彻底物理删除测试用户,避免唯一索引冲突 db.Unscoped().Exec("DELETE FROM users WHERE username = ?", username) // 1. 先尝试通过用户名查找用户(用 /api/users?username=xxx 更优,但此项目无此接口,只能用 /api/users + 遍历或注册后获取) // 先尝试登录,能登录说明用户存在 loginBody := map[string]interface{}{ "username": username, "password": password, } loginJSON, _ := json.Marshal(loginBody) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/auth/login", bytes.NewReader(loginJSON)) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) if w.Code == 200 { // 登录成功,用户已存在 var loginResp struct { Data struct { Token string `json:"token"` User struct { ID uint `json:"id"` } `json:"user"` } `json:"data"` } _ = json.Unmarshal(w.Body.Bytes(), &loginResp) token = loginResp.Data.Token userID = loginResp.Data.User.ID // update_user updateBody := map[string]interface{}{ "real_name": "API测试用户", "email": "updated_" + email, } updateJSON, _ := json.Marshal(updateBody) w2 := httptest.NewRecorder() req2, _ := http.NewRequest("POST", fmt.Sprintf("/api/users/update/%d", userID), bytes.NewReader(updateJSON)) req2.Header.Set("Content-Type", "application/json") req2.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w2, req2) if w2.Code != 200 { t.Fatalf("update_user 失败: %d, %s", w2.Code, w2.Body.String()) } // delete_user w3 := httptest.NewRecorder() req3, _ := http.NewRequest("POST", fmt.Sprintf("/api/users/delete/%d", userID), nil) req3.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w3, req3) if w3.Code != 200 { t.Fatalf("delete_user 失败: %d, %s", w3.Code, w3.Body.String()) } } // 2. 注册用户 registerBody := map[string]interface{}{ "username": username, "password": password, "email": email, } registerJSON, _ := json.Marshal(registerBody) w = httptest.NewRecorder() req, _ = http.NewRequest("POST", "/api/auth/register", bytes.NewReader(registerJSON)) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) if w.Code != 201 { t.Fatalf("注册用户失败,状态码: %d, 响应: %s", w.Code, w.Body.String()) } // 注册后调试:输出数据库密码字段 var dbUser struct{ Password string } db.Raw("SELECT password FROM users WHERE username = ?", username).Scan(&dbUser) t.Logf("注册后数据库密码字段: %s", dbUser.Password) // 避免极端情况下事务未提交,sleep 100ms time.Sleep(100 * time.Millisecond) // 3. 登录 t.Logf("登录请求体: %+v", loginBody) loginJSON, _ = json.Marshal(loginBody) w = httptest.NewRecorder() req, _ = http.NewRequest("POST", "/api/auth/login", bytes.NewReader(loginJSON)) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) if w.Code != 200 { t.Fatalf("用户登录失败,状态码: %d, 响应: %s", w.Code, w.Body.String()) } var loginResp struct { Data struct { Token string `json:"token"` User struct { ID uint `json:"id"` } `json:"user"` } `json:"data"` } _ = json.Unmarshal(w.Body.Bytes(), &loginResp) token = loginResp.Data.Token userID = loginResp.Data.User.ID // 4. 获取我的信息 w = httptest.NewRecorder() req, _ = http.NewRequest("GET", "/api/auth/me", nil) req.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w, req) if w.Code != 200 { t.Fatalf("获取我的信息失败,状态码: %d, 响应: %s", w.Code, w.Body.String()) } // 5. 用户登出 w = httptest.NewRecorder() req, _ = http.NewRequest("POST", "/api/auth/logout", nil) req.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w, req) if w.Code != 200 { t.Fatalf("用户登出失败,状态码: %d, 响应: %s", w.Code, w.Body.String()) } // 6. update_user updateBody := map[string]interface{}{ "real_name": "API测试用户2", "email": "updated2_" + email, } updateJSON, _ := json.Marshal(updateBody) w = httptest.NewRecorder() req, _ = http.NewRequest("POST", fmt.Sprintf("/api/users/update/%d", userID), bytes.NewReader(updateJSON)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w, req) if w.Code != 200 { t.Fatalf("update_user 失败: %d, %s", w.Code, w.Body.String()) } // 7. get_user w = httptest.NewRecorder() req, _ = http.NewRequest("GET", fmt.Sprintf("/api/users/%d", userID), nil) req.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w, req) if w.Code != 200 { t.Fatalf("get_user 失败: %d, %s", w.Code, w.Body.String()) } // 8. delete_user w = httptest.NewRecorder() req, _ = http.NewRequest("POST", fmt.Sprintf("/api/users/delete/%d", userID), nil) req.Header.Set("Authorization", "Bearer "+token) r.ServeHTTP(w, req) if w.Code != 200 { t.Fatalf("delete_user 失败: %d, %s", w.Code, w.Body.String()) } }