Как ввести URL-адрес для httptest.server в Голанге?

Для предложения

resp, err := client.Get(fmt.Sprintf("https://www.xxxxx/day?time=%s", time))

Если я хочу смоделировать ответ на этот client.Get() в модульном тесте, я должен использовать httptest.server, но как я могу привязать URL ( https://www.xxxxx/day?time=%s) к URL httptest.server? так что когда я вызываю client.Get(), он может вернуть ответ, который я установил ранее. По какой-то причине я не могу издеваться над клиентом здесь.

2 ответа

Как это

func NewTestServerWithURL(URL string, handler http.Handler) (*httptest.Server, error) {
    ts := httptest.NewUnstartedServer(handler)
    if URL != "" {
        l, err := net.Listen("tcp", URL)
        if err != nil {
            return nil, err
        }
        ts.Listener.Close()
        ts.Listener = l
    }
    ts.Start()
    return ts, nil
}

Обычно нет. Вы берете базовый URL-адрес с сервера и передаете его клиенту:

package main

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

func TestClient(t *testing.T) {
    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Verify request, send mock response, etc.
    }))

    defer server.Close()

    var client *http.Client
    var time time.Time

    baseURL := server.URL // Something like "http://127.0.0.1:53791"
    resp, err := client.Get(fmt.Sprintf(baseURL+"/day?time=%s", time))
    if err != nil {
            t.Fatal(err)
    }

    // Verify response body if applicable

    resp.Body.Close()
}

Http.Client - это структура, а не интерфейс, который, как вы уже видели, делает насмешку сложной. Альтернативный способ насмешки - передача внешних зависимостей, в которых нуждается подпрограмма, поэтому вместо непосредственного использования client.Get вы используете clientGet - указатель на функцию, передаваемый в подпрограмму.

Из модульного теста вы можете создать:

mockClientGet(c *http.client, url string) (resp *http.Response, err error) {
// add the test code to return what you want it to.
}

Тогда в вашем основном коде используйте:

resp, err := clientGet(client, fmt.Sprintf("https://www.xxxxx/day?time=%s", time))

При обычном вызове процедуры используйте указатель на функцию http.Client.Get, а для теста передайте указатель на макет. Это не идеальный вариант, но я не видел более приятного способа обхода внешних вызовов, не связанных с интерфейсом, - и учитывая его внешнюю зависимость, вводить его извне - неплохая вещь.

Другие вопросы по тегам