Пакет httptest

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

Создание тестового запроса

Функция httptest.NewRequest создает HTTP-запрос для использования в тестах. Первым параметром передается метод HTTP (например, GET или POST), вторым - URL-адрес, третьим - тело запроса (или nil, если тело не требуется).

gopackage main

import (
  "net/http"
  "net/http/httptest"
  "testing"
)

func TestHandler(t *testing.T) {
  req := httptest.NewRequest("GET", "/path", nil)
  res := httptest.NewRecorder()
  
  handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, world!"))
  })
  
  handler.ServeHTTP(res, req)
  
  if res.Code != http.StatusOK {
    t.Errorf("expected status OK, got %v", res.Code)
  }
}

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

go"ok"

Тестирование POST-запроса с телом

Рассмотрим пример тестирования POST-запроса с JSON-телом. Функция httptest.NewRequest позволяет передать тело запроса в виде строки или байтового слайса.

gopackage main

import (
  "bytes"
  "net/http"
  "net/http/httptest"
  "testing"
)

func TestPostHandler(t *testing.T) {
  body := []byte(`{"name": "John"}`)
  req := httptest.NewRequest("POST", "/user", bytes.NewReader(body))
  res := httptest.NewRecorder()
  
  handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
      http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
      return
    }
    w.WriteHeader(http.StatusCreated)
    w.Write([]byte("User created"))
  })
  
  handler.ServeHTTP(res, req)
  
  if res.Code != http.StatusCreated {
    t.Errorf("expected status Created, got %v", res.Code)
  }
}

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

go"ok"

Проверка заголовков ответа

Структура httptest.ResponseRecorder позволяет проверять заголовки ответа, используя метод Header.

gopackage main

import (
  "net/http"
  "net/http/httptest"
  "testing"
)

func TestHeaders(t *testing.T) {
  req := httptest.NewRequest("GET", "/api", nil)
  res := httptest.NewRecorder()
  
  handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.Write([]byte(`{"status": "ok"}`))
  })
  
  handler.ServeHTTP(res, req)
  
  contentType := res.Header().Get("Content-Type")
  if contentType != "application/json" {
    t.Errorf("expected Content-Type application/json, got %v", contentType)
  }
}

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

go"ok"

Тестирование обработчика с параметрами пути

Пакет httptest позволяет тестировать обработчики, использующие параметры пути из URL-адреса.

gopackage main

import (
  "net/http"
  "net/http/httptest"
  "strings"
  "testing"
)

func TestPathParams(t *testing.T) {
  req := httptest.NewRequest("GET", "/users/123", nil)
  res := httptest.NewRecorder()
  
  handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    path := strings.TrimPrefix(r.URL.Path, "/users/")
    if path == "123" {
      w.Write([]byte("User found"))
    } else {
      http.Error(w, "not found", http.StatusNotFound)
    }
  })
  
  handler.ServeHTTP(res, req)
  
  if res.Code != http.StatusOK {
    t.Errorf("expected status OK, got %v", res.Code)
  }
}

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

go"ok"

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

  • функцию httptest.NewRequest,
    которая создает тестовый HTTP-запрос
  • структуру httptest.ResponseRecorder,
    которая записывает ответы обработчика
  • тип testing.T,
    который используется для управления тестами
  • пакет net/http/pprof,
    который предоставляет профилирование HTTP-сервера