package testutil import ( "context" "database/sql" "fmt" "testing" "github.com/jackc/pgx/v5/pgxpool" _ "github.com/jackc/pgx/v5/stdlib" "github.com/pressly/goose/v3" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) func SetupTestDB(t *testing.T) *pgxpool.Pool { t.Helper() ctx := context.Background() container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "postgres:16-alpine", ExposedPorts: []string{"5432/tcp"}, Env: map[string]string{ "POSTGRES_DB": "test_db", "POSTGRES_USER": "test_user", "POSTGRES_PASSWORD": "test_pass", }, WaitingFor: wait.ForListeningPort("5432/tcp"), }, Started: true, }) if err != nil { t.Fatalf("failed to start container: %v", err) } t.Cleanup(func() { container.Terminate(ctx) }) host, err := container.Host(ctx) if err != nil { t.Fatalf("failed to get host: %v", err) } port, err := container.MappedPort(ctx, "5432") if err != nil { t.Fatalf("failed to get port: %v", err) } dsn := fmt.Sprintf("postgres://test_user:test_pass@%s:%s/test_db?sslmode=disable", host, port.Port()) // Run migrations with goose db, err := sql.Open("pgx", dsn) if err != nil { t.Fatalf("failed to open db for migrations: %v", err) } defer db.Close() if err := goose.Up(db, "../../../migrations"); err != nil { // Try relative path from different test locations if err2 := goose.Up(db, "../../migrations"); err2 != nil { t.Fatalf("failed to run migrations: %v (also tried: %v)", err, err2) } } pool, err := pgxpool.New(ctx, dsn) if err != nil { t.Fatalf("failed to create pool: %v", err) } t.Cleanup(func() { pool.Close() }) return pool }