How to Test Your Go API

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.

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.”

Hello! I'm a gaming enthusiast, a history buff, a cinema lover, connected to the news, and I enjoy exploring different lifestyles. I'm Yaman Şener/trioner.com, a web content creator who brings all these interests together to offer readers in-depth analyses, informative content, and inspiring perspectives. I'm here to accompany you through the vast spectrum of the digital world.

Leave a Reply

Your email address will not be published. Required fields are marked *