45 Menggunakan httptest
untuk Test End-to-End
Pengujian merupakan bagian tak terpisahkan dari pengembangan software modern. Salah satu tantangan utamanya adalah memastikan seluruh stack aplikasi berjalan sesuai ekspektasi, terutama untuk aplikasi berbasis HTTP seperti yang umum kita temui pada service berbasis Go. Dalam konteks ini, Go menyediakan paket httptest
yang powerful untuk menguji aplikasi dari sudut pandang end-to-end (E2E).
Pada artikel ini, saya akan membahas praktik penggunaan httptest
untuk test E2E di aplikasi Go. Penjelasan akan mencakup:
- Apa itu
httptest
dan kegunaannya - Studi kasus aplikasi sederhana
- Langkah-langkah membangun E2E test
- Simulasi request-response
- Tips & best practice
- Tabel perbandingan
- Diagram alur test
Mari kita mulai!
Apa Itu httptest
?
httptest
adalah paket resmi dari standar library Go yang menyediakan utilitas untuk pengujian HTTP. Paket ini biasanya digunakan untuk :
- Membuat test server (
httptest.NewServer
) - Membuat request dan response recorder (
httptest.NewRecorder
) - Menguji handler dan end-point
Dengan paket ini, kita dapat mensimulasikan HTTP request/response tanpa harus menjalankan server secara penuh di luar testing environment. Cocok untuk test integration maupun E2E di aplikasi Go.
Studi Kasus: Aplikasi Notes API
Saya akan menggunakan studi kasus aplikasi API sederhana sebagai contoh — Notes API, dengan dua end-point:
POST /notes
: membuat note baruGET /notes
: mengambil seluruh notes
Represtasikan handlers berikut:
// note.go
type Note struct {
ID int `json:"id"`
Body string `json:"body"`
}
var notes = []Note{}
var currentID = 1
func createNoteHandler(w http.ResponseWriter, r *http.Request) {
var note Note
json.NewDecoder(r.Body).Decode(¬e)
note.ID = currentID
currentID++
notes = append(notes, note)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(note)
}
func getNotesHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(notes)
}
Routing sederhana menggunakan http.ServeMux
:
func NewRouter() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/notes", func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
createNoteHandler(w, r)
} else if r.Method == http.MethodGet {
getNotesHandler(w, r)
} else {
http.NotFound(w, r)
}
})
return mux
}
Implementasi Test End-to-End dengan httptest
Bagaimana cara menggunakan httptest
untuk menguji API ini dari ujung ke ujung? Berikut langkah-langkah intinya:
1. Membuat Test Server
Gunakan httptest.NewServer
untuk menjalankan handler sebagai server HTTP asli pada port random.
func setupTestServer() *httptest.Server {
router := NewRouter()
server := httptest.NewServer(router)
return server
}
2. Test flow: Simulasi Use Case E2E
Kita akan membuat satu integration test yang:
- Mengirim POST
/notes
dengan payload JSON - Mengirim GET
/notes
dan mengecek note yang baru saja dibuat ada di hasil response
func TestE2ENotesAPI(t *testing.T) {
server := setupTestServer()
defer server.Close()
// Step 1: Create a note
note := map[string]string{"body": "Belajar httptest"}
payload, _ := json.Marshal(note)
resp, err := http.Post(server.URL+"/notes",
"application/json", bytes.NewBuffer(payload))
require.NoError(t, err)
require.Equal(t, http.StatusCreated, resp.StatusCode)
var created Note
json.NewDecoder(resp.Body).Decode(&created)
resp.Body.Close()
assert.Equal(t, "Belajar httptest", created.Body)
assert.NotZero(t, created.ID)
// Step 2: Get all notes
resp, err = http.Get(server.URL + "/notes")
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
var notesResp []Note
json.NewDecoder(resp.Body).Decode(¬esResp)
resp.Body.Close()
assert.Len(t, notesResp, 1)
assert.Equal(t, created, notesResp[0])
}
3. Diagram Alur Test
Mari visualisasikan alurnya dengan diagram mermaid yang sederhana:
sequenceDiagram participant T as Test Code participant S as httptest.Server participant H as Handlers T->>S: POST /notes (dengan payload) S->>H: createNoteHandler H-->>S: Response 201 (note baru) S-->>T: Kirim response 201 T->>S: GET /notes S->>H: getNotesHandler H-->>S: Response 200 (daftar notes) S-->>T: Kirim response 200 beserta notes
Tabel: Kelebihan dan Kekurangan
Aspek | Kelebihan httptest | Kekurangan httptest |
---|---|---|
Dependency | Tidak butuh server eksternal | Tidak bisa testing infra eksternal (misal koneksi DB sebenarnya) |
Speed | Super cepat, in-memory | Tidak cover e2e sesungguhnya di production |
Realisme | Mendekati testing nyata (full HTTP stack) | Masih di lingkungan test, bukan real server |
Isolasi | Mudah reset state, cocok untuk parallel test | State sederhana, persistence terbatas |
Simulasi Failure Case
Bagaimana jika kita ingin test error, misal payload malformed?
func TestCreateNote_MalformedPayload(t *testing.T) {
server := setupTestServer()
defer server.Close()
resp, err := http.Post(server.URL+"/notes",
"application/json", strings.NewReader("{broken_json}"))
require.NoError(t, err)
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
}
Tambahkan validasi di handler:
func createNoteHandler(w http.ResponseWriter, r *http.Request) {
var note Note
err := json.NewDecoder(r.Body).Decode(¬e)
if err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
// ... lanjutkan proses seperti sebelumnya
}
Tips dan Best Practice
- Gunakan
httptest.NewServer
untuk full handler test, bukan hanya unit handler. - Pastikan state selalu reset sebelum setiap test E2E. Hindari side effect!
- Gunakan helper/setup function untuk memperpendek kode boilerplate test server.
- Gunakan assertion dari library seperti testify untuk pengecekan yang readable.
- Testing variasi edge-case (payload invalid, metode tak dikenali, dsb).
Kesimpulan
Dengan httptest
, Go memungkinkan penulisan E2E test untuk API HTTP dengan mudah dan cepat, tanpa perlu server eksternal. Dari simulasi request hingga pengecekan response, kita dapat memastikan end-point berjalan sesuai ekspektasi sebelum naik ke lingkungan production.
Apakah httptest
sudah otomatis cukup untuk semua kebutuhan E2E? Tidak selalu, terutama jika aplikasi Anda bergantung pada beberapa service eksternal. Namun, untuk sebagian besar kasus API Go, tes berbasis httptest
adalah fondasi yang kuat dan sangat recommended untuk diterapkan sejak hari pertama development.
Integrasikan dengan pipeline CI Anda — dan nikmati proses confidence boost setiap fitur baru didorong!
Baca juga:
Selamat mencoba, dan semoga bermanfaat!
67. Retry Mechanism di Client gRPC
68. Kompresi Data (gzip) di gRPC
Artikel Terhangat
99 Kontribusi ke Open Source graphql-go
10 Oct 2025
98 Membuat Plugin Sendiri untuk graphql-go
10 Oct 2025
96 Migrasi REST API ke GraphQL
10 Oct 2025
94 Studi Kasus: Dashboard Admin Real-time
10 Oct 2025

99 Kontribusi ke Open Source graphql-go

98 Membuat Plugin Sendiri untuk graphql-go

96 Migrasi REST API ke GraphQL
