material_manage_system/internal/testutil/isolation.go

73 lines
2.2 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.

package testutil
import (
"bytes"
"database/sql"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/go-sql-driver/mysql"
"github.com/wmms/wmms/pkg/database"
)
// NewIsolationDB 在显式配置的 MySQL 服务器(TEST_DB_DSN 指向 company_isolation_test*)上
// 创建一个一次性的库,载入 scripts/init.sql 的空库结构,并把 database.DB 指向它;测试结束
// 自动删库并恢复。与 repository 侧的同名测试集共用同一台服务器与同一套空库结构,
// 让 Service 层的事务场景能直接跑真实 MySQL。未配置 TEST_DB_DSN 时跳过。
func NewIsolationDB(t *testing.T) *sql.DB {
t.Helper()
dsn := os.Getenv("TEST_DB_DSN")
if dsn == "" {
t.Skip("real MySQL integration requires TEST_DB_DSN")
}
cfg, err := mysql.ParseDSN(dsn)
if err != nil {
t.Fatal(err)
}
if !strings.HasPrefix(cfg.DBName, "company_isolation_test") {
t.Fatal("TEST_DB_DSN must name a company_isolation_test schema")
}
cfg.DBName = ""
cfg.MultiStatements = true
cfg.ParseTime = true
admin, err := sql.Open("mysql", cfg.FormatDSN())
if err != nil {
t.Fatal(err)
}
name := fmt.Sprintf("company_isolation_test_%d", time.Now().UnixNano())
if _, err = admin.Exec("CREATE DATABASE `" + name + "` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); err != nil {
admin.Close()
t.Fatal(err)
}
cfg.DBName = name
db, err := sql.Open("mysql", cfg.FormatDSN())
if err != nil {
t.Fatal(err)
}
original := database.DB
database.DB = db
t.Cleanup(func() { database.DB = original; db.Close(); admin.Exec("DROP DATABASE `" + name + "`"); admin.Close() })
content, err := os.ReadFile(filepath.Join("..", "..", "scripts", "init.sql"))
if err != nil {
t.Fatal(err)
}
// init.sql 可能带 UTF-8 BOM,按字节剥掉,避免第一行 CREATE TABLE 解析失败。
content = bytes.TrimPrefix(content, []byte{0xEF, 0xBB, 0xBF})
var lines []string
for _, line := range strings.Split(string(content), "\n") {
if strings.HasPrefix(line, "CREATE DATABASE") || strings.HasPrefix(line, "USE ") {
continue
}
lines = append(lines, line)
}
if _, err = db.Exec(strings.Join(lines, "\n")); err != nil {
t.Fatalf("initialize scripts/init.sql: %v", err)
}
return db
}