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
47 Membuat Mutation Login dan Signup
08 Aug 2025
69. Studi Kasus: Retry dan Backoff Strategy
08 Aug 2025
46 Menambahkan Middleware Autentikasi JWT
08 Aug 2025
68. Kompresi Data (gzip) di gRPC
08 Aug 2025
67. Retry Mechanism di Client gRPC
08 Aug 2025
44 Mocking Database untuk Test Resolver
08 Aug 2025
66. Deadline dan Timeout pada gRPC
08 Aug 2025

47 Membuat Mutation Login dan Signup

69. Studi Kasus: Retry dan Backoff Strategy

46 Menambahkan Middleware Autentikasi JWT

68. Kompresi Data (gzip) di gRPC

67. Retry Mechanism di Client gRPC

44 Mocking Database untuk Test Resolver
