init
This commit is contained in:
367
backend/tests/integration/database_test.go
Normal file
367
backend/tests/integration/database_test.go
Normal file
@@ -0,0 +1,367 @@
|
||||
//go:build legacytests
|
||||
// +build legacytests
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"quyun/v2/app/config"
|
||||
"quyun/v2/app/database"
|
||||
)
|
||||
|
||||
// TestUser 测试用户模型
|
||||
type TestUser struct {
|
||||
ID int `gorm:"primaryKey"`
|
||||
Name string `gorm:"size:100;not null"`
|
||||
Email string `gorm:"size:100;unique;not null"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||
}
|
||||
|
||||
// TestDatabaseConnection 测试数据库连接
|
||||
func TestDatabaseConnection(t *testing.T) {
|
||||
Convey("数据库连接测试", t, func() {
|
||||
var db *gorm.DB
|
||||
var sqlDB *sql.DB
|
||||
var testConfig *config.Config
|
||||
var testDBName string
|
||||
|
||||
Convey("当准备测试数据库时", func() {
|
||||
testDBName = "v2_test_integration"
|
||||
testConfig = &config.Config{
|
||||
Database: config.DatabaseConfig{
|
||||
Host: "localhost",
|
||||
Port: 5432,
|
||||
Database: testDBName,
|
||||
Username: "postgres",
|
||||
Password: "password",
|
||||
SslMode: "disable",
|
||||
MaxIdleConns: 5,
|
||||
MaxOpenConns: 20,
|
||||
ConnMaxLifetime: 30 * time.Minute,
|
||||
},
|
||||
}
|
||||
|
||||
Convey("应该能够连接到数据库", func() {
|
||||
dsn := testConfig.Database.GetDSN()
|
||||
var err error
|
||||
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
So(err, ShouldBeNil)
|
||||
So(db, ShouldNotBeNil)
|
||||
|
||||
sqlDB, err = db.DB()
|
||||
So(err, ShouldBeNil)
|
||||
So(sqlDB, ShouldNotBeNil)
|
||||
|
||||
// 设置连接池
|
||||
sqlDB.SetMaxIdleConns(testConfig.Database.MaxIdleConns)
|
||||
sqlDB.SetMaxOpenConns(testConfig.Database.MaxOpenConns)
|
||||
sqlDB.SetConnMaxLifetime(testConfig.Database.ConnMaxLifetime)
|
||||
|
||||
// 测试连接
|
||||
err = sqlDB.Ping()
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("应该能够创建测试表", func() {
|
||||
err := db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS integration_test_users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
email VARCHAR(100) UNIQUE NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`).Error
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("当测试数据库操作时", func() {
|
||||
Convey("应该能够创建记录", func() {
|
||||
user := TestUser{
|
||||
Name: "Integration Test User",
|
||||
Email: "integration@example.com",
|
||||
}
|
||||
|
||||
result := db.Create(&user)
|
||||
So(result.Error, ShouldBeNil)
|
||||
So(result.RowsAffected, ShouldEqual, 1)
|
||||
So(user.ID, ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
Convey("应该能够查询记录", func() {
|
||||
// 先插入测试数据
|
||||
user := TestUser{
|
||||
Name: "Query Test User",
|
||||
Email: "query@example.com",
|
||||
}
|
||||
db.Create(&user)
|
||||
|
||||
// 查询记录
|
||||
var result TestUser
|
||||
err := db.First(&result, "email = ?", "query@example.com").Error
|
||||
So(err, ShouldBeNil)
|
||||
So(result.Name, ShouldEqual, "Query Test User")
|
||||
So(result.Email, ShouldEqual, "query@example.com")
|
||||
})
|
||||
|
||||
Convey("应该能够更新记录", func() {
|
||||
// 先插入测试数据
|
||||
user := TestUser{
|
||||
Name: "Update Test User",
|
||||
Email: "update@example.com",
|
||||
}
|
||||
db.Create(&user)
|
||||
|
||||
// 更新记录
|
||||
result := db.Model(&user).Update("name", "Updated Integration User")
|
||||
So(result.Error, ShouldBeNil)
|
||||
So(result.RowsAffected, ShouldEqual, 1)
|
||||
|
||||
// 验证更新
|
||||
var updatedUser TestUser
|
||||
err := db.First(&updatedUser, user.ID).Error
|
||||
So(err, ShouldBeNil)
|
||||
So(updatedUser.Name, ShouldEqual, "Updated Integration User")
|
||||
})
|
||||
|
||||
Convey("应该能够删除记录", func() {
|
||||
// 先插入测试数据
|
||||
user := TestUser{
|
||||
Name: "Delete Test User",
|
||||
Email: "delete@example.com",
|
||||
}
|
||||
db.Create(&user)
|
||||
|
||||
// 删除记录
|
||||
result := db.Delete(&user)
|
||||
So(result.Error, ShouldBeNil)
|
||||
So(result.RowsAffected, ShouldEqual, 1)
|
||||
|
||||
// 验证删除
|
||||
var deletedUser TestUser
|
||||
err := db.First(&deletedUser, user.ID).Error
|
||||
So(err, ShouldEqual, gorm.ErrRecordNotFound)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("当测试事务时", func() {
|
||||
Convey("应该能够执行事务操作", func() {
|
||||
// 开始事务
|
||||
tx := db.Begin()
|
||||
So(tx, ShouldNotBeNil)
|
||||
|
||||
// 在事务中插入数据
|
||||
user := TestUser{
|
||||
Name: "Transaction Test User",
|
||||
Email: "transaction@example.com",
|
||||
}
|
||||
result := tx.Create(&user)
|
||||
So(result.Error, ShouldBeNil)
|
||||
So(result.RowsAffected, ShouldEqual, 1)
|
||||
|
||||
// 查询事务中的数据
|
||||
var count int64
|
||||
tx.Model(&TestUser{}).Count(&count)
|
||||
So(count, ShouldEqual, 1)
|
||||
|
||||
// 提交事务
|
||||
err := tx.Commit().Error
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// 验证数据已提交
|
||||
db.Model(&TestUser{}).Count(&count)
|
||||
So(count, ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
Convey("应该能够回滚事务", func() {
|
||||
// 开始事务
|
||||
tx := db.Begin()
|
||||
|
||||
// 在事务中插入数据
|
||||
user := TestUser{
|
||||
Name: "Rollback Test User",
|
||||
Email: "rollback@example.com",
|
||||
}
|
||||
tx.Create(&user)
|
||||
|
||||
// 回滚事务
|
||||
err := tx.Rollback().Error
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// 验证数据已回滚
|
||||
var count int64
|
||||
db.Model(&TestUser{}).Where("email = ?", "rollback@example.com").Count(&count)
|
||||
So(count, ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("当测试批量操作时", func() {
|
||||
Convey("应该能够批量插入记录", func() {
|
||||
users := []TestUser{
|
||||
{Name: "Batch User 1", Email: "batch1@example.com"},
|
||||
{Name: "Batch User 2", Email: "batch2@example.com"},
|
||||
{Name: "Batch User 3", Email: "batch3@example.com"},
|
||||
}
|
||||
|
||||
result := db.Create(&users)
|
||||
So(result.Error, ShouldBeNil)
|
||||
So(result.RowsAffected, ShouldEqual, 3)
|
||||
|
||||
// 验证批量插入
|
||||
var count int64
|
||||
db.Model(&TestUser{}).Where("email LIKE ?", "batch%@example.com").Count(&count)
|
||||
So(count, ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("应该能够批量更新记录", func() {
|
||||
// 先插入测试数据
|
||||
users := []TestUser{
|
||||
{Name: "Batch Update 1", Email: "batchupdate1@example.com"},
|
||||
{Name: "Batch Update 2", Email: "batchupdate2@example.com"},
|
||||
}
|
||||
db.Create(&users)
|
||||
|
||||
// 批量更新
|
||||
result := db.Model(&TestUser{}).
|
||||
Where("email LIKE ?", "batchupdate%@example.com").
|
||||
Update("name", "Batch Updated User")
|
||||
So(result.Error, ShouldBeNil)
|
||||
So(result.RowsAffected, ShouldEqual, 2)
|
||||
|
||||
// 验证更新
|
||||
var updatedCount int64
|
||||
db.Model(&TestUser{}).
|
||||
Where("name = ?", "Batch Updated User").
|
||||
Count(&updatedCount)
|
||||
So(updatedCount, ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("当测试查询条件时", func() {
|
||||
Convey("应该能够使用各种查询条件", func() {
|
||||
// 插入测试数据
|
||||
testUsers := []TestUser{
|
||||
{Name: "Alice", Email: "alice@example.com"},
|
||||
{Name: "Bob", Email: "bob@example.com"},
|
||||
{Name: "Charlie", Email: "charlie@example.com"},
|
||||
{Name: "Alice Smith", Email: "alice.smith@example.com"},
|
||||
}
|
||||
db.Create(&testUsers)
|
||||
|
||||
Convey("应该能够使用 LIKE 查询", func() {
|
||||
var users []TestUser
|
||||
err := db.Where("name LIKE ?", "Alice%").Find(&users).Error
|
||||
So(err, ShouldBeNil)
|
||||
So(len(users), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("应该能够使用 IN 查询", func() {
|
||||
var users []TestUser
|
||||
err := db.Where("name IN ?", []string{"Alice", "Bob"}).Find(&users).Error
|
||||
So(err, ShouldBeNil)
|
||||
So(len(users), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("应该能够使用 BETWEEN 查询", func() {
|
||||
var users []TestUser
|
||||
err := db.Where("id BETWEEN ? AND ?", 1, 3).Find(&users).Error
|
||||
So(err, ShouldBeNil)
|
||||
So(len(users), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
Convey("应该能够使用多条件查询", func() {
|
||||
var users []TestUser
|
||||
err := db.Where("name LIKE ? AND email LIKE ?", "%Alice%", "%example.com").Find(&users).Error
|
||||
So(err, ShouldBeNil)
|
||||
So(len(users), ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reset(func() {
|
||||
// 清理测试表
|
||||
if db != nil {
|
||||
db.Exec("DROP TABLE IF EXISTS integration_test_users")
|
||||
}
|
||||
// 关闭数据库连接
|
||||
if sqlDB != nil {
|
||||
sqlDB.Close()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// TestDatabaseConnectionPool 测试数据库连接池
|
||||
func TestDatabaseConnectionPool(t *testing.T) {
|
||||
Convey("数据库连接池测试", t, func() {
|
||||
var db *gorm.DB
|
||||
var sqlDB *sql.DB
|
||||
|
||||
Convey("当配置连接池时", func() {
|
||||
testConfig := &config.Config{
|
||||
Database: config.DatabaseConfig{
|
||||
Host: "localhost",
|
||||
Port: 5432,
|
||||
Database: "v2_test_pool",
|
||||
Username: "postgres",
|
||||
Password: "password",
|
||||
SslMode: "disable",
|
||||
MaxIdleConns: 5,
|
||||
MaxOpenConns: 10,
|
||||
ConnMaxLifetime: 5 * time.Minute,
|
||||
},
|
||||
}
|
||||
|
||||
dsn := testConfig.Database.GetDSN()
|
||||
var err error
|
||||
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
sqlDB, err = db.DB()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("应该能够设置连接池参数", func() {
|
||||
sqlDB.SetMaxIdleConns(testConfig.Database.MaxIdleConns)
|
||||
sqlDB.SetMaxOpenConns(testConfig.Database.MaxOpenConns)
|
||||
sqlDB.SetConnMaxLifetime(testConfig.Database.ConnMaxLifetime)
|
||||
|
||||
// 验证设置
|
||||
stats := sqlDB.Stats()
|
||||
So(stats.MaxOpenConns, ShouldEqual, testConfig.Database.MaxOpenConns)
|
||||
So(stats.MaxIdleConns, ShouldEqual, testConfig.Database.MaxIdleConns)
|
||||
})
|
||||
|
||||
Convey("应该能够监控连接池状态", func() {
|
||||
// 获取初始状态
|
||||
initialStats := sqlDB.Stats()
|
||||
So(initialStats.OpenConnections, ShouldEqual, 0)
|
||||
|
||||
// 执行一些查询来创建连接
|
||||
for i := 0; i < 3; i++ {
|
||||
sqlDB.Ping()
|
||||
}
|
||||
|
||||
// 获取使用后的状态
|
||||
afterStats := sqlDB.Stats()
|
||||
So(afterStats.OpenConnections, ShouldBeGreaterThan, 0)
|
||||
So(afterStats.InUse, ShouldBeGreaterThan, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Reset(func() {
|
||||
// 关闭数据库连接
|
||||
if sqlDB != nil {
|
||||
sqlDB.Close()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user