Как тестировать сетевые запросы в Go?

В Go существует несколько подходов для тестирования сетевых запросов. Рассмотрим два основных подхода: использование фиктивного (mock) сервера и использование реального сервера, запущенного во время тестирования.

1. Использование фиктивного сервера:

Фиктивный сервер (mock server) — это сервер, созданный специально для тестирования, который имитирует поведение реального сервера. Это позволяет нам контролировать и проверять запросы и ответы, которые мы получаем.

Для создания фиктивного сервера в Go можно использовать пакеты, такие как httptest или gomock. httptest предоставляет функциональность для создания и настройки фиктивных HTTP-серверов, а gomock позволяет создавать фиктивные объекты и задавать им поведение.

Вот пример использования httptest для создания фиктивного сервера и отправки запроса:

func TestMyHandler(t *testing.T) {
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("hello world"))
    })

    server := httptest.NewServer(handler)
    defer server.Close()

    // отправляем запрос на фиктивный сервер
    resp, err := http.Get(server.URL)
    if err != nil {
        t.Fatal(err)
    }

    // проверяем статус код и тело ответа
    if resp.StatusCode != http.StatusOK {
        t.Errorf("expected status OK, got %d", resp.StatusCode)
    }

    body, err := io.ReadAll(resp.Body)
    resp.Body.Close()
    if err != nil {
        t.Fatal(err)
    }

    if string(body) != "hello world" {
        t.Errorf("expected body 'hello world', got %s", string(body))
    }
}

2. Использование реального сервера:

В другом подходе мы запускаем реальный сервер во время тестирования. Для этого мы можем использовать пакет net/http/httptest, который позволяет нам создавать инстанс HTTP-сервера и отправлять запросы к нему во время тестирования.

Пример использования httptest для тестирования реального сервера:

func TestMyHandler(t *testing.T) {
    // создаем инстанс реального сервера
    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("hello world"))
    }))
    defer server.Close()

    // отправляем запрос на реальный сервер
    resp, err := http.Get(server.URL)
    if err != nil {
        t.Fatal(err)
    }

    // проверяем статус код и тело ответа
    if resp.StatusCode != http.StatusOK {
        t.Errorf("expected status OK, got %d", resp.StatusCode)
    }

    body, err := io.ReadAll(resp.Body)
    resp.Body.Close()
    if err != nil {
        t.Fatal(err)
    }

    if string(body) != "hello world" {
        t.Errorf("expected body 'hello world', got %s", string(body))
    }
}

В обоих случаях мы используем стандартный пакет net/http для выполнения запросов и проверки ответов. Мы также используем пакет testing для написания и запуска тестов.

При тестировании сетевых запросов важно учитывать различные сценарии и обработку ошибок, чтобы проверить, что наш код обрабатывает все возможные варианты использования. Мы можем использовать различные функции и методы, предоставляемые пакетами httptest и net/http, чтобы убедиться, что наш код выполняет все необходимые проверки и взаимодействует с сервером правильно.