feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers
This commit is contained in:
222
internal/integration/integration_test.go
Normal file
222
internal/integration/integration_test.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite" // 纯 Go SQLite,注册 "sqlite" 驱动
|
||||
gormsqlite "gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"github.com/user-management-system/internal/domain"
|
||||
"github.com/user-management-system/internal/repository"
|
||||
)
|
||||
|
||||
var integDBCounter int64
|
||||
|
||||
func setupTestDB(t *testing.T) *gorm.DB {
|
||||
t.Helper()
|
||||
id := atomic.AddInt64(&integDBCounter, 1)
|
||||
dsn := fmt.Sprintf("file:integtestdb%d?mode=memory&cache=private", id)
|
||||
db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
|
||||
DriverName: "sqlite",
|
||||
DSN: dsn,
|
||||
}), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("打开测试数据库失败: %v", err)
|
||||
}
|
||||
if err := db.AutoMigrate(&domain.User{}, &domain.Role{}, &domain.Permission{}, &domain.Device{}); err != nil {
|
||||
t.Fatalf("数据库迁移失败: %v", err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func cleanupTestDB(t *testing.T, db *gorm.DB) {
|
||||
t.Helper()
|
||||
sqlDB, _ := db.DB()
|
||||
sqlDB.Close()
|
||||
}
|
||||
|
||||
// setupTestServer 测试服务器
|
||||
func setupTestServer(t *testing.T) *httptest.Server {
|
||||
t.Helper()
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/v1/auth/register", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"code":0,"message":"success","data":{"user_id":1}}`))
|
||||
})
|
||||
mux.HandleFunc("/api/v1/auth/login", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"code":0,"message":"success","data":{"access_token":"test-token"}}`))
|
||||
})
|
||||
mux.HandleFunc("/api/v1/users/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"code":0,"message":"success","data":{"id":1,"username":"testuser"}}`))
|
||||
})
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
// TestDatabaseIntegration 测试数据库集成
|
||||
func TestDatabaseIntegration(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer cleanupTestDB(t, db)
|
||||
repo := repository.NewUserRepository(db)
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("CreateUser", func(t *testing.T) {
|
||||
user := &domain.User{
|
||||
Phone: domain.StrPtr("13800138000"),
|
||||
Username: "integrationuser",
|
||||
Password: "hashedpassword",
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
if err := repo.Create(ctx, user); err != nil {
|
||||
t.Fatalf("创建用户失败: %v", err)
|
||||
}
|
||||
if user.ID == 0 {
|
||||
t.Error("用户ID不应为0")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("FindUser", func(t *testing.T) {
|
||||
user, err := repo.GetByUsername(ctx, "integrationuser")
|
||||
if err != nil {
|
||||
t.Fatalf("查询用户失败: %v", err)
|
||||
}
|
||||
if domain.DerefStr(user.Phone) != "13800138000" {
|
||||
t.Errorf("Phone = %v, want 13800138000", domain.DerefStr(user.Phone))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("UpdateUser", func(t *testing.T) {
|
||||
user, _ := repo.GetByUsername(ctx, "integrationuser")
|
||||
user.Nickname = "已更新"
|
||||
if err := repo.Update(ctx, user); err != nil {
|
||||
t.Fatalf("更新用户失败: %v", err)
|
||||
}
|
||||
found, _ := repo.GetByID(ctx, user.ID)
|
||||
if found.Nickname != "已更新" {
|
||||
t.Errorf("Nickname = %v, want 已更新", found.Nickname)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DeleteUser", func(t *testing.T) {
|
||||
user, _ := repo.GetByUsername(ctx, "integrationuser")
|
||||
if err := repo.Delete(ctx, user.ID); err != nil {
|
||||
t.Fatalf("删除用户失败: %v", err)
|
||||
}
|
||||
_, err := repo.GetByUsername(ctx, "integrationuser")
|
||||
if err == nil {
|
||||
t.Error("删除后查询应返回错误")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestTransactionIntegration 测试事务集成
|
||||
func TestTransactionIntegration(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer cleanupTestDB(t, db)
|
||||
|
||||
t.Run("TransactionRollback", func(t *testing.T) {
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
user := &domain.User{
|
||||
Phone: domain.StrPtr("13811111111"),
|
||||
Username: "txrollbackuser",
|
||||
Password: "hashedpassword",
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
if err := tx.Create(user).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New("模拟错误,触发回滚")
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("事务应该失败")
|
||||
}
|
||||
|
||||
var count int64
|
||||
db.Model(&domain.User{}).Where("username = ?", "txrollbackuser").Count(&count)
|
||||
if count > 0 {
|
||||
t.Error("事务回滚后用户不应存在")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TransactionCommit", func(t *testing.T) {
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
user := &domain.User{
|
||||
Phone: domain.StrPtr("13822222222"),
|
||||
Username: "txcommituser",
|
||||
Password: "hashedpassword",
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
return tx.Create(user).Error
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("事务失败: %v", err)
|
||||
}
|
||||
|
||||
var count int64
|
||||
db.Model(&domain.User{}).Where("username = ?", "txcommituser").Count(&count)
|
||||
if count != 1 {
|
||||
t.Error("事务提交后用户应存在")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestAPIIntegration 测试HTTP API集成
|
||||
func TestAPIIntegration(t *testing.T) {
|
||||
server := setupTestServer(t)
|
||||
defer server.Close()
|
||||
|
||||
t.Run("RegisterEndpoint", func(t *testing.T) {
|
||||
resp, err := http.Post(server.URL+"/api/v1/auth/register", "application/json", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("StatusCode = %d, want 200", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("LoginEndpoint", func(t *testing.T) {
|
||||
resp, err := http.Post(server.URL+"/api/v1/auth/login", "application/json", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("StatusCode = %d, want 200", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GetUserEndpoint", func(t *testing.T) {
|
||||
resp, err := http.Get(server.URL + "/api/v1/users/1")
|
||||
if err != nil {
|
||||
t.Fatalf("请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("StatusCode = %d, want 200", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user