Тип httptest.ResponseRecorder
Тип httptest.ResponseRecorder реализует интерфейс http.ResponseWriter
и используется для записи ответов при тестировании обработчиков HTTP.
Он сохраняет все данные, которые передаются в методы записи, позволяя
впоследствии проверить статус-код, заголовки и тело ответа.
Основное преимущество использования ResponseRecorder заключается
в том, что тесты могут выполняться без реального запуска HTTP-сервера,
что делает их быстрее и надежнее.
При создании httptest.ResponseRecorder с помощью функции
httptest.NewRecorder, он инициализируется с пустым телом ответа
и статус-кодом по умолчанию 200 OK. В процессе тестирования
вы можете передать его в ваш обработчик вместо реального
http.ResponseWriter, а затем проверить записанные данные.
Синтаксис
Для создания экземпляра ResponseRecorder используется функция:
recorder := httptest.NewRecorder()
После этого recorder можно передать в тестируемый обработчик:
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
req := httptest.NewRequest("GET", "/", nil)
handler.ServeHTTP(recorder, req)
Основные поля и методы
httptest.ResponseRecorder предоставляет несколько важных полей
для анализа записанного ответа:
// Code - статус-код ответа (по умолчанию 200)
Code int
// HeaderMap - заголовки ответа
HeaderMap http.Header
// Body - буфер с телом ответа
Body *bytes.Buffer
// Flushed - флаг, указывающий, был ли вызван Flush
Flushed bool
Пример
Давайте напишем тест для обработчика, который возвращает JSON-ответ:
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestJSONHandler(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
response := map[string]string{"message": "success"}
json.NewEncoder(w).Encode(response)
})
req := httptest.NewRequest("POST", "/api", nil)
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, req)
if recorder.Code != http.StatusCreated {
t.Errorf("Expected status %d, got %d", http.StatusCreated, recorder.Code)
}
if contentType := recorder.HeaderMap.Get("Content-Type"); contentType != "application/json" {
t.Errorf("Expected Content-Type application/json, got %s", contentType)
}
expected := `{"message":"success"}` + "\n"
if recorder.Body.String() != expected {
t.Errorf("Expected body %s, got %s", expected, recorder.Body.String())
}
}
Результат выполнения теста:
"PASS"
Пример
В этом примере тестируем обработчик с различными статус-кодами и условиями:
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
)
func TestStatusHandler(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Query().Get("status") {
case "404":
http.NotFound(w, r)
case "500":
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
default:
fmt.Fprintf(w, "OK")
}
})
tests := []struct {
name string
status string
wantCode int
wantBody string
}{
{"Default", "", http.StatusOK, "OK"},
{"NotFound", "404", http.StatusNotFound, "404 page not found\n"},
{"ServerError", "500", http.StatusInternalServerError, "Internal Server Error\n"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest("GET", "/?status="+tt.status, nil)
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, req)
if recorder.Code != tt.wantCode {
t.Errorf("Expected status %d, got %d", tt.wantCode, recorder.Code)
}
if recorder.Body.String() != tt.wantBody {
t.Errorf("Expected body %s, got %s", tt.wantBody, recorder.Body.String())
}
})
}
}
Результат выполнения кода:
"PASS"
Смотрите также
-
функцию
httptest.NewRequest,
которая создает HTTP-запрос для тестирования -
пакет
httptest,
который предоставляет утилиты для HTTP-тестирования -
метод
testing.T.Error,
который сообщает об ошибке в тесте без остановки выполнения -
метод
testing.T.Log,
который выводит сообщение в лог теста