Testing Middleware in Isolation
Middleware'ni ALOHIDA sinash
Mashinaning tormoz tizimini sinash uchun BUTUN mashinani YO'LGA chiqarish shart emas — tormoz qismini STENDGA o'rnatib, ALOHIDA bosim berib ko'rish MUMKIN va ANIQROQ. Middleware'ni sinashda ham xuddi shunday: BUTUN ilovani (BookStore, real handler'lar) ISHGA TUSHIRISH shart emas — middleware'ni SODDA, "soxta" (fake/spy) next handler bilan ALOHIDA sinash mumkin, bu esa test nimani TEKSHIRAYOTGANINI ANIQROQ qiladi.
package main
import (
"net/http"
"net/http/httptest"
"testing"
)
var apiKeys = map[string]string{"key-abc": "Acme Corp"}
func requireAPIKey(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
key := r.Header.Get("X-API-Key")
if _, ok := apiKeys[key]; !ok {
w.WriteHeader(http.StatusUnauthorized)
return
}
next(w, r)
}
}
func TestRequireAPIKey(t *testing.T) {
var calledNext bool
// SPY handler: HAQIQIY ish qilmaydi, faqat "meni chaqirishdimi?" deb BELGILAYDI
next := func(w http.ResponseWriter, r *http.Request) {
calledNext = true
w.WriteHeader(http.StatusOK)
}
handler := requireAPIKey(next)
tests := []struct {
name string
apiKey string
wantStatus int
wantCalled bool
}{
{"kalit yoq", "", http.StatusUnauthorized, false},
{"togri kalit", "key-abc", http.StatusOK, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
calledNext = false
req := httptest.NewRequest("GET", "/books", nil)
if tt.apiKey != "" {
req.Header.Set("X-API-Key", tt.apiKey)
}
rec := httptest.NewRecorder()
handler(rec, req)
if rec.Code != tt.wantStatus {
t.Errorf("status = %d, kutilgan %d", rec.Code, tt.wantStatus)
}
if calledNext != tt.wantCalled {
t.Errorf("calledNext = %v, kutilgan %v", calledNext, tt.wantCalled)
}
})
}
}next — HAQIQIY BookStore yoki JSON javob YOZMAYDI, u FAQAT calledNext = true deb BELGILAYDI. Bu — MIDDLEWARE'ga xos test naqshi: biz createHandler yoki getHandlerNING to'g'ri ishlashini emas, requireAPIKeyNING O'ZI to'g'ri ishlashini ("ruxsat bo'lmasa next chaqirilmasin", "ruxsat bo'lsa chaqirilsin") sinaymiz. Agar next chaqirilgan bo'lsa-yu, lekin STATUS kutilganidan farq qilsa — bu middleware muammosi EMAS, nextNING o'ZI muammo, deb ANIQ ajratish mumkin.
calledNext — ikkita AJRALIB turadigan narsani BIR VAQTDA tekshiradi: (1) status kod TO'G'RImi, (2) next CHAQIRILDIMI yoki YO'Qmi. Faqat statusni tekshirish YETARLI EMAS: masalan middleware xato bilan HAM 200 qaytarib, HAM nextni chaqirmasligi mumkin — calledNext buni FOSH qiladi.
>_ Exercise
NOTO'G'RI (lekin BO'SH bo'lmagan) kalit holatini ham jadvalga qo'shing.
- •tests jadvaliga {"notogri kalit", "wrong", http.StatusUnauthorized, false} qatorini qo'shing
- •BOSHQA hech narsani o'zgartirmang
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
Middleware'ni ALOHIDA sinash — HAQIQIY biznes handler o'rniga, oddiy "spy" (kuzatuvchi) funksiya bilan, middleware'ning FAQAT o'ziga xos xatti-harakatini (chaqirilishi yoki chaqirilmasligi) TEKSHIRISHGA imkon beradi.
NEXT UP
Putting It All Together: Wiring the Full API
$ go run main.go
Kodingizni ishga tushiring