You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.4 KiB
179 lines
5.4 KiB
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())
|
|
}
|
|
}
|
|
|