Testing ain’t optional — if you skip it, your codebase will become spaghetti real quick. Luckily, Go ships with a built-in testing framework, and the ecosystem gives you extra toys like testify, gomock, and testcontainers-go.
Table of Contents
Here’s the 3 types of tests you’ll be running:
How to Test Your Go API
1️⃣ Unit Tests (isolated stuff)
- Test one thing at a time → a single func/method.
- No DB, no network, no “real” side effects.
- Use mocks if your code depends on external systems.
📌 Example:
func Add(a, b int) int { return a + b }
func TestAdd(t *testing.T) {
got := Add(1, 2)
want := 3
if got != want {
t.Errorf("Add(1, 2) = %d; want %d", got, want)
}
}
💡 Pro tip: Use subtests + table-driven tests to cover multiple cases fast.
2️⃣ Integration Tests (real deps)
- Here you test how multiple parts work together.
- DB, file system, network? Yep, they’re in play.
- Use SQLite in-memory or spin up real containers (see testcontainers).
📌 Example with HTTP handler:
func handler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"message": "hello world"}`))
}
func TestMyHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
handler(w, req)
resp := w.Result()
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
if string(data) != `{"message": "hello world"}` {
t.Errorf("expected hello world, got %s", data)
}
}
3️⃣ E2E Tests (treat API like a black box)
- Spin up your API and test it as a user would.
- Hit endpoints with
http.Client
or tools like Cypress/Playwright for web. - Focus on flows: register → login → create → list → delete.
📌 Example:
func TestRegisterAndLogin(t *testing.T) {
resp, _ := http.Post("http://localhost:8080/register",
"application/json",
strings.NewReader(`{"username":"user","password":"pass"}`))
if resp.StatusCode != http.StatusOK {
t.Fatalf("register failed: %d", resp.StatusCode)
}
resp, _ = http.Post("http://localhost:8080/login",
"application/json",
strings.NewReader(`{"username":"user","password":"pass"}`))
if resp.StatusCode != http.StatusOK {
t.Fatalf("login failed: %d", resp.StatusCode)
}
}
⚙️ Bonus Tools
- gomock → auto-gen mocks for interfaces.
- testify → clean assertions (
assert.Equal
,require.NoError
). - testcontainers-go → spin up real DBs (Postgres, Redis, etc.) in Docker during tests.
🏆 TL;DR Strategy
- Unit tests → fast, small, mocked.
- Integration → real DB/services.
- E2E → test whole system like a user.
Do this combo and you’ll ship Go APIs that don’t break the second someone clicks “Login.”
- How to Recover Permanently Deleted Files on Mac
- How to Remove Microsoft Store Ads Showing Up on Windows
- How to Fix Nvidia Driver Crashes on Windows 11
- What to Do If Your Phone Is Lost or Stolen
- How to Recover Your Google Account If You Forget Your Password
- Google Issues Emergency Security Warning to 2.5 Billion Gmail Users
- Designing Your REST API with Go: A Complete Guide