1
0
Files
nex/backend/tests/mysql/migration_test.go
lanyuanxiaoyao 5b401e29cb feat: 新增 MySQL 专项测试能力
- 新增 backend/tests/mysql/ 目录,包含 Docker Compose 配置和测试文件
- 新增 Makefile 命令: test-mysql, test-mysql-up, test-mysql-down, test-mysql-quick
- 使用 build tag 控制测试启用,默认不运行
- 测试覆盖: 迁移正确性、外键约束、UNIQUE 约束、并发写入
- 发现 statsRepo.Record 存在并发 bug(检查-然后-操作竞态条件)
2026-04-23 12:25:55 +08:00

127 lines
4.0 KiB
Go

//go:build mysql
package mysql
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMigration_TablesExist(t *testing.T) {
db := SetupMySQLTestDB(t)
var tables []string
err := db.Raw("SHOW TABLES").Scan(&tables).Error
require.NoError(t, err)
expectedTables := []string{"providers", "models", "usage_stats"}
for _, expected := range expectedTables {
assert.Contains(t, tables, expected, "表 %s 应存在", expected)
}
}
func TestMigration_TableColumns(t *testing.T) {
db := SetupMySQLTestDB(t)
t.Run("providers 表字段", func(t *testing.T) {
var columns []struct {
Field string
Type string
Null string
}
err := db.Raw("SHOW COLUMNS FROM providers").Scan(&columns).Error
require.NoError(t, err)
columnMap := make(map[string]string)
for _, col := range columns {
columnMap[col.Field] = col.Type
}
assert.Contains(t, columnMap["id"], "varchar", "id 应为 VARCHAR 类型")
assert.Contains(t, columnMap["name"], "varchar", "name 应为 VARCHAR 类型")
assert.Contains(t, columnMap["api_key"], "varchar", "api_key 应为 VARCHAR 类型")
assert.Contains(t, columnMap["base_url"], "varchar", "base_url 应为 VARCHAR 类型")
assert.Contains(t, columnMap["protocol"], "varchar", "protocol 应为 VARCHAR 类型")
assert.Contains(t, columnMap["enabled"], "tinyint", "enabled 应为 TINYINT (BOOLEAN) 类型")
assert.Contains(t, columnMap["created_at"], "datetime", "created_at 应为 DATETIME 类型")
assert.Contains(t, columnMap["updated_at"], "datetime", "updated_at 应为 DATETIME 类型")
})
t.Run("models 表字段", func(t *testing.T) {
var columns []struct {
Field string
Type string
}
err := db.Raw("SHOW COLUMNS FROM models").Scan(&columns).Error
require.NoError(t, err)
columnMap := make(map[string]string)
for _, col := range columns {
columnMap[col.Field] = col.Type
}
assert.Contains(t, columnMap["id"], "varchar", "id 应为 VARCHAR 类型")
assert.Contains(t, columnMap["provider_id"], "varchar", "provider_id 应为 VARCHAR 类型")
assert.Contains(t, columnMap["model_name"], "varchar", "model_name 应为 VARCHAR 类型")
assert.Contains(t, columnMap["enabled"], "tinyint", "enabled 应为 TINYINT (BOOLEAN) 类型")
assert.Contains(t, columnMap["created_at"], "datetime", "created_at 应为 DATETIME 类型")
})
t.Run("usage_stats 表字段", func(t *testing.T) {
var columns []struct {
Field string
Type string
}
err := db.Raw("SHOW COLUMNS FROM usage_stats").Scan(&columns).Error
require.NoError(t, err)
columnMap := make(map[string]string)
for _, col := range columns {
columnMap[col.Field] = col.Type
}
assert.Contains(t, columnMap["id"], "int", "id 应为 INT 类型")
assert.Contains(t, columnMap["provider_id"], "varchar", "provider_id 应为 VARCHAR 类型")
assert.Contains(t, columnMap["model_name"], "varchar", "model_name 应为 VARCHAR 类型")
assert.Contains(t, columnMap["request_count"], "int", "request_count 应为 INT 类型")
assert.Contains(t, columnMap["date"], "date", "date 应为 DATE 类型")
})
}
func TestMigration_IndexesExist(t *testing.T) {
db := SetupMySQLTestDB(t)
t.Run("models 表索引", func(t *testing.T) {
var indexes []struct {
KeyName string
}
err := db.Raw("SHOW INDEX FROM models").Scan(&indexes).Error
require.NoError(t, err)
indexMap := make(map[string]bool)
for _, idx := range indexes {
indexMap[idx.KeyName] = true
}
assert.True(t, indexMap["idx_models_provider_id"], "idx_models_provider_id 索引应存在")
assert.True(t, indexMap["idx_models_model_name"], "idx_models_model_name 索引应存在")
})
t.Run("usage_stats 表索引", func(t *testing.T) {
var indexes []struct {
KeyName string
}
err := db.Raw("SHOW INDEX FROM usage_stats").Scan(&indexes).Error
require.NoError(t, err)
indexMap := make(map[string]bool)
for _, idx := range indexes {
indexMap[idx.KeyName] = true
}
assert.True(t, indexMap["idx_usage_stats_provider_model_date"], "idx_usage_stats_provider_model_date 索引应存在")
})
}