Skip to Content

Test Utilities

The testutil package provides testing utilities for Gofasta applications including test database setup and teardown, an HTTP test client for integration tests, fixture loading, and assertion helpers.

Import

import "github.com/gofastadev/gofasta/pkg/testutil"

Key Types

TestDB

type TestDB struct { DB *gorm.DB Config config.DatabaseConfig }

TestClient

type TestClient struct { Handler http.Handler Token string Headers map[string]string }

TestResponse

type TestResponse struct { StatusCode int Body []byte Headers http.Header } func (r *TestResponse) JSON(dest interface{}) error func (r *TestResponse) String() string

Key Functions

Database Helpers

FunctionSignatureDescription
SetupTestDBfunc SetupTestDB(t *testing.T, models ...interface{}) *TestDBCreates a test database with auto-migration
TeardownTestDBfunc (tdb *TestDB) Teardown(t *testing.T)Drops all tables and closes the connection
TruncateTablesfunc (tdb *TestDB) TruncateTables(t *testing.T, tables ...string)Truncates specified tables between tests
SeedTestDatafunc (tdb *TestDB) SeedTestData(t *testing.T, records ...interface{})Inserts test records into the database

HTTP Test Client

FunctionSignatureDescription
NewTestClientfunc NewTestClient(handler http.Handler) *TestClientCreates a test client for the given handler
WithTokenfunc (tc *TestClient) WithToken(token string) *TestClientSets the Authorization header
WithHeaderfunc (tc *TestClient) WithHeader(key, value string) *TestClientSets a custom header
Getfunc (tc *TestClient) Get(t *testing.T, path string) *TestResponseSends a GET request
Postfunc (tc *TestClient) Post(t *testing.T, path string, body interface{}) *TestResponseSends a POST request with JSON body
Putfunc (tc *TestClient) Put(t *testing.T, path string, body interface{}) *TestResponseSends a PUT request with JSON body
Deletefunc (tc *TestClient) Delete(t *testing.T, path string) *TestResponseSends a DELETE request

Fixture Helpers

FunctionSignatureDescription
LoadFixturefunc LoadFixture(t *testing.T, path string, dest interface{})Loads a JSON fixture file into a struct
LoadFixturesfunc LoadFixtures(t *testing.T, dir string) map[string]json.RawMessageLoads all JSON files from a directory
GenerateTokenfunc GenerateToken(t *testing.T, claims auth.Claims) stringGenerates a test JWT token

Assertion Helpers

FunctionSignatureDescription
AssertStatusfunc AssertStatus(t *testing.T, resp *TestResponse, expected int)Asserts the HTTP status code
AssertJSONfunc AssertJSON(t *testing.T, resp *TestResponse, key string, expected interface{})Asserts a JSON field value
AssertContainsfunc AssertContains(t *testing.T, resp *TestResponse, substring string)Asserts the response body contains a string
AssertDBHasfunc AssertDBHas(t *testing.T, db *gorm.DB, table string, conditions map[string]interface{})Asserts a record exists in the database
AssertDBMissingfunc AssertDBMissing(t *testing.T, db *gorm.DB, table string, conditions map[string]interface{})Asserts a record does not exist

Usage

Integration Test with Test Database

func TestUserRepository_Create(t *testing.T) { tdb := testutil.SetupTestDB(t, &User{}) defer tdb.Teardown(t) repo := NewUserRepository(tdb.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) testutil.AssertDBHas(t, tdb.DB, "users", map[string]interface{}{ "email": "jane@example.com", "role": "editor", }) }

HTTP Integration Test

func TestUserController_Create(t *testing.T) { tdb := testutil.SetupTestDB(t, &User{}) defer tdb.Teardown(t) handler := setupRouter(tdb.DB) // your router setup function client := testutil.NewTestClient(handler) token := testutil.GenerateToken(t, auth.Claims{ UserID: "admin-123", Roles: []string{"admin"}, }) resp := client.WithToken(token).Post(t, "/api/users", map[string]string{ "name": "Jane Doe", "email": "jane@example.com", "role": "editor", }) testutil.AssertStatus(t, resp, http.StatusCreated) testutil.AssertJSON(t, resp, "data.email", "jane@example.com") testutil.AssertDBHas(t, tdb.DB, "users", map[string]interface{}{ "email": "jane@example.com", }) }

Using Fixtures

Create fixture files in testdata/:

testdata/users.json:

[ {"name": "Alice", "email": "alice@test.com", "role": "admin"}, {"name": "Bob", "email": "bob@test.com", "role": "editor"} ]

Load and use in tests:

func TestUserService_List(t *testing.T) { tdb := testutil.SetupTestDB(t, &User{}) defer tdb.Teardown(t) var users []User testutil.LoadFixture(t, "testdata/users.json", &users) tdb.SeedTestData(t, users) service := NewUserService(NewUserRepository(tdb.DB)) result, total, err := service.List(context.Background(), types.DefaultQueryParams()) assert.NoError(t, err) assert.Equal(t, int64(2), total) assert.Len(t, result, 2) }

Table-Driven Tests

func TestUserController_GetUser(t *testing.T) { tdb := testutil.SetupTestDB(t, &User{}) defer tdb.Teardown(t) handler := setupRouter(tdb.DB) client := testutil.NewTestClient(handler) token := testutil.GenerateToken(t, auth.Claims{UserID: "user-1", Roles: []string{"admin"}}) tests := []struct { name string userID string wantStatus int }{ {"existing user", "user-1", http.StatusOK}, {"non-existing user", "user-999", http.StatusNotFound}, {"invalid uuid", "not-a-uuid", http.StatusBadRequest}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { resp := client.WithToken(token).Get(t, "/api/users/"+tt.userID) testutil.AssertStatus(t, resp, tt.wantStatus) }) } }
  • Config — Test database configuration
  • Auth — GenerateToken uses auth package claims
  • Models — Models used in test database setup
Last updated on