Тип httptest.ResponseRecorder

Тип httptest.ResponseRecorder реализует интерфейс http.ResponseWriter и используется для записи ответов при тестировании обработчиков HTTP. Он сохраняет все данные, которые передаются в методы записи, позволяя впоследствии проверить статус-код, заголовки и тело ответа. Основное преимущество использования ResponseRecorder заключается в том, что тесты могут выполняться без реального запуска HTTP-сервера, что делает их быстрее и надежнее.

При создании httptest.ResponseRecorder с помощью функции httptest.NewRecorder, он инициализируется с пустым телом ответа и статус-кодом по умолчанию 200 OK. В процессе тестирования вы можете передать его в ваш обработчик вместо реального http.ResponseWriter, а затем проверить записанные данные.

Синтаксис

Для создания экземпляра ResponseRecorder используется функция:

gorecorder := httptest.NewRecorder()

После этого recorder можно передать в тестируемый обработчик:

gohandler := 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 предоставляет несколько важных полей для анализа записанного ответа:

go// Code - статус-код ответа (по умолчанию 200)
Code int

// HeaderMap - заголовки ответа
HeaderMap http.Header

// Body - буфер с телом ответа
Body *bytes.Buffer

// Flushed - флаг, указывающий, был ли вызван Flush
Flushed bool

Пример

Давайте напишем тест для обработчика, который возвращает JSON-ответ:

gopackage 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())
  }
}

Результат выполнения теста:

go"PASS"

Пример

В этом примере тестируем обработчик с различными статус-кодами и условиями:

gopackage 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())
      }
    })
  }
}

Результат выполнения кода:

go"PASS"

Смотрите также

  • функцию httptest.NewRequest,
    которая создает HTTP-запрос для тестирования
  • пакет httptest,
    который предоставляет утилиты для HTTP-тестирования
  • метод testing.T.Error,
    который сообщает об ошибке в тесте без остановки выполнения
  • метод testing.T.Log,
    который выводит сообщение в лог теста