вторник, 18 августа 2020 г.

Пакет httptest в Golang

Пакет httptest предоставляет утилиты для тестирования HTTP.

Функция NewRequest

func NewRequest(method, target string, body io.Reader) *http.Request

NewRequest возвращает новый входящий Request сервера, подходящий для передачи http.Handler для тестирования.

target является RFC 7230 "request-target": это может быть либо путь, либо абсолютный URL. Если target является абсолютный URL-адрес, используется имя хоста из URL-адреса. В противном случае используется example.com.

В поле TLS устанавливается фиктивное значение, отличное от nil, если target имеет схему "https".

Request.Proto всегда HTTP/1.1.

Пустой method означает "GET".

Предоставленное body может быть nil. Если тело имеет тип *bytes.Reader, *strings.Reader или *bytes.Buffer, устанавливается Request.ContentLength.

NewRequest паникует при ошибке для простоты использования при тестировании, где паника допустима.

Чтобы сгенерировать клиентский HTTP-запрос вместо запроса сервера, используйте функцию NewRequest в пакете net/http.

Тип ResponseRecorder

ResponseRecorder - это реализация http.ResponseWriter, которая записывает его изменения для последующей проверки в тестах.

type ResponseRecorder struct {
    // Code - это код ответа HTTP, 
    // установленный WriteHeader.
    //
    // Обратите внимание, что если Handler 
    // никогда не вызывает WriteHeader или Write,
    // Code может оказаться 0, 
    // а не неявным http.StatusOK. 
    // Чтобы получить неявное значение, 
    // используйте метод Result.
    Code int

    // HeaderMap содержит заголовки, 
    // явно установленные Handler.
    // Это внутренняя деталь.
    //
    // Не рекомендуется: 
    // HeaderMap существует для исторической совместимости
    // и не должны использоваться. 
    // Чтобы получить доступ к заголовкам, 
    // возвращаемым обработчиком,
    // использовать карту Response.Header, 
    // возвращенную методом Result.
    HeaderMap http.Header

    // Body - это буфер, 
    // в который отправляются вызовы Write Handler'а.
    // Если nil, Writes игнорируется.
    Body *bytes.Buffer

    // Flushed, флаг вызвал ли Handler Flush.
    Flushed bool
    // содержит отфильтрованные или неэкспортированные поля
}

Пример использования NewRequest, NewRecorder

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "net/http/httptest"
)

func main() {
    handler := func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "<html><body>Hello World!</body></html>")
    }

    req := httptest.NewRequest("GET", "http://example.com/foo", nil)
    w := httptest.NewRecorder()
    handler(w, req)

    resp := w.Result()
    body, _ := ioutil.ReadAll(resp.Body)

    fmt.Println(resp.StatusCode)
    fmt.Println(resp.Header.Get("Content-Type"))
    fmt.Println(string(body))

}

Вывод:

200
text/html; charset=utf-8
<html><body>Hello World!</body></html>

Тип Server

Server - это HTTP-сервер, который прослушивает выбранный системой порт на локальном интерфейсе обратной связи для использования в сквозных (end-to-end) HTTP-тестах.

type Server struct {
    // базовый URL формы 
    // http://ipaddr:port без слеша в конце
    URL      string 
    Listener net.Listener

    // EnableHTTP2 контролирует, включен ли HTTP/2
    // на сервере. Он должен быть установлен между вызовами
    // NewUnstartedServer и Server.StartTLS.
    EnableHTTP2 bool // Go 1.14

    // TLS - это необязательная конфигурация TLS, 
    // заполненная новой конфигурацией после запуска TLS. 
    // Если установлено на 
    // не запущенном сервере до вызова StartTLS,
    // существующие поля копируются в новый конфиг.
    TLS *tls.Config

    // Config может быть изменен 
    // после вызова NewUnstartedServer и
    // перед Start или StartTLS.
    Конфиг *http.Server
    // содержит отфильтрованные или неэкспортированные поля
}

Пример использования Server

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, client")
    }))
    defer ts.Close()

    res, err := http.Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }
    greeting, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", greeting)
}

Вывод:

Hello, client

Пример использования Server (HTTP2)

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %s", r.Proto)
    }))
    ts.EnableHTTP2 = true
    ts.StartTLS()
    defer ts.Close()

    res, err := ts.Client().Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }
    greeting, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s", greeting)

}

Вывод:

Hello, HTTP/2.0

Функция NewServer

func NewServer(handler http.Handler) *Server

NewServer запускается и возвращает новый Server. По завершении вызывающий должен вызвать Close, чтобы закрыть его.

Функция NewTLSServer

func NewTLSServer(handler http.Handler) *Server

NewTLSServer запускается и возвращает новый Server с использованием TLS. По завершении вызывающий должен вызвать Close, чтобы закрыть его.

Пример использования NewTLSServer

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
)

func main() {
    ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, client")
    }))
    defer ts.Close()

    client := ts.Client()
    res, err := client.Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }

    greeting, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", greeting)
}

Вывод:

Hello, client


Читайте также:


Комментариев нет:

Отправить комментарий