Test Utilities
The testutil package provides testing utilities for Gofasta applications, including test database setup using testcontainers-go with PostgreSQL, automatic migration, and cleanup.
Import
import "github.com/gofastadev/gofasta/pkg/testutil/testdb"Key Functions
Database Helpers
| Function | Signature | Description |
|---|---|---|
SetupTestDB | func SetupTestDB(t *testing.T) *gorm.DB | Spins up a PostgreSQL container, runs migrations, and returns a connected *gorm.DB |
RunMigrations | func RunMigrations(db *gorm.DB) error | Applies base SQL migrations to the test database |
Usage
Integration Test with Test Database
SetupTestDB starts a PostgreSQL container using testcontainers, runs base migrations, and returns a *gorm.DB. The container is automatically cleaned up when the test finishes via t.Cleanup.
func TestUserRepository_Create(t *testing.T) {
db := testdb.SetupTestDB(t)
// Auto-migrate your models
db.AutoMigrate(&User{})
repo := NewUserRepository(db)
user := &User{
Name: "Jane Doe",
Email: "jane@example.com",
Role: "editor",
}
err := repo.Create(context.Background(), user)
assert.NoError(t, err)
assert.NotEmpty(t, user.ID)
// Verify the record exists
var found User
db.First(&found, "email = ?", "jane@example.com")
assert.Equal(t, "editor", found.Role)
}Base Migrations
SetupTestDB automatically runs the following base migrations:
- Creates the
citextextension - Creates an
update_updated_at_column()trigger function - Creates a
prevent_delete_non_deletable()trigger function - Creates an
increment_record_version()trigger function
These match the trigger functions that gofasta-generated models expect (updated_at maintenance, soft-delete guards, record versioning). You then add your own model migrations with db.AutoMigrate(...).
HTTP Integration Test
func TestUserController_Create(t *testing.T) {
db := testdb.SetupTestDB(t)
db.AutoMigrate(&User{})
handler := setupRouter(db) // your router setup function
req := httptest.NewRequest(http.MethodPost, "/api/users", strings.NewReader(`{
"name": "Jane Doe",
"email": "jane@example.com",
"role": "editor"
}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+testToken)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
assert.Equal(t, http.StatusCreated, rec.Code)
var found User
db.First(&found, "email = ?", "jane@example.com")
assert.Equal(t, "Jane Doe", found.Name)
}Table-Driven Tests
func TestUserController_GetUser(t *testing.T) {
db := testdb.SetupTestDB(t)
db.AutoMigrate(&User{})
handler := setupRouter(db)
tests := []struct {
name string
userID string
wantStatus int
}{
{"existing user", "valid-uuid", http.StatusOK},
{"non-existing user", "missing-uuid", http.StatusNotFound},
{"invalid uuid", "not-a-uuid", http.StatusBadRequest},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/api/users/"+tt.userID, nil)
req.Header.Set("Authorization", "Bearer "+testToken)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
assert.Equal(t, tt.wantStatus, rec.Code)
})
}
}Related Pages
Last updated on