Files
lijiaoqiao/supply-api/internal/repository/account_integration_test.go
Your Name 2bc4a00ecd test(supply-api): add repository integration suite and runner
Add repository integration probes, repository policy tests, the compose-based integration runner, and the matching usage documentation. Align the runner environment with both repository and middleware integration test expectations, and verify with fresh repository tests, integration-tag test runs, bash -n, and docker-compose config before commit.
2026-04-11 11:25:19 +08:00

245 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build integration
// +build integration
package repository
import (
"context"
"os"
"testing"
"github.com/jackc/pgx/v5/pgxpool"
)
// getTestDB 获取测试数据库连接
func getTestDB(t *testing.T) *pgxpool.Pool {
t.Helper()
host := os.Getenv("SUPPLY_API_DB_HOST")
if host == "" {
host = "/var/run/postgresql"
}
port := os.Getenv("SUPPLY_API_DB_PORT")
if port == "" {
port = "5432"
}
user := os.Getenv("SUPPLY_API_DB_USER")
if user == "" {
user = "long"
}
password := os.Getenv("SUPPLY_API_DB_PASSWORD")
dbName := os.Getenv("SUPPLY_API_DB_NAME")
if dbName == "" {
dbName = "supply_test"
}
// 构建 DSN - 如果 host 是路径Unix socket使用 host= 参数
var dsn string
if host[0] == '/' {
dsn = "postgres://" + user + ":" + password + "@/" + dbName + "?host=" + host + "&sslmode=disable"
} else {
dsn = "postgres://" + user + ":" + password + "@" + host + ":" + port + "/" + dbName + "?sslmode=disable"
}
pool, err := pgxpool.New(context.Background(), dsn)
if err != nil {
t.Skipf("跳过集成测试:无法连接数据库: %v", err)
return nil
}
if err := pool.Ping(context.Background()); err != nil {
pool.Close()
t.Skipf("跳过集成测试:无法 ping 数据库: %v", err)
return nil
}
t.Cleanup(func() {
pool.Close()
})
return pool
}
// TestAccountRepository_Create_Integration 集成测试:创建账号
func TestAccountRepository_Create_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 验证连接成功
var result int
err := pool.QueryRow(context.Background(), "SELECT 1").Scan(&result)
if err != nil {
t.Fatalf("查询失败: %v", err)
}
if result != 1 {
t.Fatalf("预期结果 1实际: %d", result)
}
t.Log("集成测试:数据库连接成功")
}
// TestAccountRepository_GetByID_Integration 集成测试:获取账号
func TestAccountRepository_GetByID_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 验证 supply_accounts 表存在
var tableName string
err := pool.QueryRow(context.Background(), "SELECT table_name FROM information_schema.tables WHERE table_name = 'supply_accounts'").Scan(&tableName)
if err != nil {
t.Skipf("跳过supply_accounts 表不存在: %v", err)
}
t.Log("集成测试supply_accounts 表存在")
}
// TestAccountRepository_Update_Integration 集成测试:更新账号(乐观锁)
func TestAccountRepository_Update_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 验证表结构包含 version 字段(乐观锁)
var columnExists bool
err := pool.QueryRow(context.Background(), `
SELECT EXISTS(
SELECT 1 FROM information_schema.columns
WHERE table_name = 'supply_accounts' AND column_name = 'version'
)
`).Scan(&columnExists)
if err != nil || !columnExists {
t.Skip("跳过supply_accounts 表缺少 version 字段(乐观锁)")
}
t.Log("集成测试supply_accounts 表包含 version 字段(乐观锁)")
}
// TestAccountRepository_List_Integration 集成测试:列出账号
func TestAccountRepository_List_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 列出所有表
rows, err := pool.Query(context.Background(), `
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
`)
if err != nil {
t.Fatalf("查询表列表失败: %v", err)
}
defer rows.Close()
count := 0
for rows.Next() {
var name string
rows.Scan(&name)
count++
}
if count == 0 {
t.Fatal("预期至少有一些表")
}
t.Logf("集成测试:数据库包含 %d 个表", count)
}
// TestAccountRepository_GetWithdrawableBalance_Integration 集成测试:获取可提现余额
func TestAccountRepository_GetWithdrawableBalance_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 验证 supply_accounts 表存在并且有相关字段
var accountID int64
err := pool.QueryRow(context.Background(), "SELECT COALESCE(MAX(id), 0) FROM supply_accounts").Scan(&accountID)
if err != nil {
t.Logf("集成测试supply_accounts 表为空或不存在: %v", err)
} else {
t.Logf("集成测试supply_accounts 最大 ID = %d", accountID)
}
}
// TestAccountRepository_OptimisticLock_Integration 集成测试:乐观锁冲突
func TestAccountRepository_OptimisticLock_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 验证 version 字段存在
var versionCol int
err := pool.QueryRow(context.Background(), `
SELECT COUNT(*) FROM information_schema.columns
WHERE table_name = 'supply_accounts' AND column_name = 'version'
`).Scan(&versionCol)
if err != nil || versionCol == 0 {
t.Skip("跳过supply_accounts 表缺少 version 字段")
}
t.Log("集成测试:乐观锁字段验证通过")
}
// TestAccountRepository_Transaction_Integration 集成测试:事务操作
func TestAccountRepository_Transaction_Integration(t *testing.T) {
if testing.Short() {
t.Skip("跳过集成测试short mode")
}
pool := getTestDB(t)
if pool == nil {
return
}
// 测试事务
tx, err := pool.Begin(context.Background())
if err != nil {
t.Fatalf("开始事务失败: %v", err)
}
defer tx.Rollback(context.Background())
var result int
err = tx.QueryRow(context.Background(), "SELECT 1").Scan(&result)
if err != nil {
t.Fatalf("事务内查询失败: %v", err)
}
err = tx.Commit(context.Background())
if err != nil {
t.Fatalf("提交事务失败: %v", err)
}
t.Log("集成测试:事务操作成功")
}