368 lines
9.7 KiB
Go
368 lines
9.7 KiB
Go
//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()
|
|
}
|
|
})
|
|
})
|
|
}
|