package test import ( "api_yal/internal/config" "api_yal/internal/models" "fmt" "net/http" "net/http/httptest" "testing" "github.com/go-chi/chi/v5" "github.com/ory/dockertest/v3" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) var ( TestDB *gorm.DB TestRouter *chi.Mux TestConfig *config.Config ) func setupTestDatabase() (*gorm.DB, func()) { pool, err := dockertest.NewPool("") if err != nil { panic(fmt.Sprintf("Could not connect to Docker: %s", err)) } // Запускаем PostgreSQL контейнер resource, err := pool.Run("postgres", "15-alpine", []string{ "POSTGRES_PASSWORD=testpass", "POSTGRES_USER=testuser", "POSTGRES_DB=testdb", }) if err != nil { panic(fmt.Sprintf("Could not start PostgreSQL: %s", err)) } // Ждем пока база поднимется var db *gorm.DB if err := pool.Retry(func() error { var err error dsn := fmt.Sprintf("host=localhost port=%s user=testuser password=testpass dbname=testdb sslmode=disable", resource.GetPort("5432/tcp")) db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), // Отключаем логи GORM в тестах }) if err != nil { return err } sqlDB, err := db.DB() if err != nil { return err } return sqlDB.Ping() }); err != nil { panic(fmt.Sprintf("Could not connect to DB: %s", err)) } // Выполняем миграции models := []interface{}{ &models.Account{}, &models.UpdateHistory{}, &models.Object{}, &models.RatingVote{}, &models.VoteBreakdown{}, &models.Rating{}, &models.Feedback{}, &models.Comment{}, &models.Appeal{}, &models.AppealHistory{}, &models.PasswordReset{}, } for _, model := range models { db.AutoMigrate(model) } // Очищаем базу после тестов cleanup := func() { if err := pool.Purge(resource); err != nil { fmt.Printf("Could not purge resource: %s\n", err) } } return db, cleanup } // ExecuteRequest выполняет HTTP запрос и возвращает ответ func ExecuteRequest(req *http.Request) *httptest.ResponseRecorder { rr := httptest.NewRecorder() TestRouter.ServeHTTP(rr, req) return rr } // GetAuthHeader возвращает заголовок авторизации func GetAuthHeader(token string) http.Header { headers := http.Header{} headers.Set("Authorization", "Bearer "+token) headers.Set("Content-Type", "application/json") return headers } // CleanDatabase очищает все таблицы между тестами func CleanDatabase(t *testing.T) { tables := []string{ "users", "accounts", "objects", "feedbacks", "comments", "ratings", "appeals", "appeal_histories", } for _, table := range tables { if err := TestDB.Exec(fmt.Sprintf("TRUNCATE TABLE %s RESTART IDENTITY CASCADE", table)).Error; err != nil { t.Logf("Warning: could not truncate %s: %v", table, err) } } }