Я пытаюсь протестировать клиент REST Api в Golang, используя mux и httptest

#go #net-http #mux

#Вперед #net-http #mux

Вопрос:

Здесь я пытаюсь написать тест для REST-клиента, записывая apiOutput в http.ResponseWriter, но я всегда получаю {nil nil} в качестве apiResponse.

Может ли кто-нибудь помочь мне указать на ошибку?

 func Test_Do(t *testing.T) {

    mux := http.NewServeMux()
    server := httptest.NewServer(mux)
    t.Cleanup(server.Close)

    config := NewClientConfig()
    config.BaseURL = server.URL

    client, err := NewClient(config)

    if err != nil {
        t.Fatal(err)
    }

    apiResponse := struct {
        Id    string      `json:"id"`
        Error error       `json:"error"`
        Data  interface{} `json:"data"`
    }{}

    apiOutput := []byte(`{
        "id":"1",
        "error":nil,
        "data":[{"IP": "1.2.2.3"}]}`)

    mux.HandleFunc("/api/v1/hosts", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write(apiOutput)
    })

    t.Run("Get Host Details", func(t *testing.T) {
        req, err := client.MakeGetRequest(http.MethodGet, "/api/v1/hosts", nil)
        if err != nil {
            t.Fatal(err)
        }
        resp, err1 := client.Do(req, amp;apiResponse)

        if err1 != nil {
            t.Fatalf("failed with statusCode: %d, error: %s", resp.StatusCode, err1)
        }
        if apiResponse.Id != "1" || apiResponse.Error != nil {
            t.Errorf("Client.Do() problem unmarshaling problem: got %#v", apiResponse)
        }
        fmt.Printf("%v", apiResponse)
    })
}
  
 func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
    resp, err := c.HTTPClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if errorResponse := c.CheckResponse(resp); errorResponse != nil {
        return resp, errorResponse
    }
    if v != nil {
        if w, ok := v.(io.Writer); ok {
            io.Copy(w, resp.Body)
        } else {
            decErr := json.NewDecoder(resp.Body).Decode(v)
            if decErr == io.EOF {
                decErr = nil // ignore EOF errors caused by empty response body
            }
            if decErr != nil {
                err = decErr
            }
        }
    }
    return resp, err
}
  

Вывод:

     Test_Do/Get_Host_Details: clients_test.go:269: Client.Do() problem unmarshaling problem: got struct { Id string "json:"id""; Error error "json:"error""; Data interface {} "json:"data"" }{Id:"", Error:error(nil), Data:interface {}(nil)}
{ <nil> <nil>}
  

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

1. @MuffinTop обновлен с Client.Do

2. Что, если вы измените w.Write(apiOutput) на fmt.Fprint(w, apiOutput) ? Именно так я пишу HTTP-ответы, и у меня это работает без сбоев. Также задайте код состояния для макетного ответа. w.WriteHeader(http.StatusOK)

3. Я получил ту же ошибку, что и я, я попробовал это. изменение на fmt.Fprint(w, apiOutput)?

4. возможно, это может быть полезно посмотреть youtube.com/watch?v=hVFEV-ieeew

5. Обратите внимание, что nil это недопустимое значение json, поэтому ваше apiOutput текущее значение сломано и приведет к сбою демаршализации / декодирования. Обратите также внимание, что вы не можете использовать error тип интерфейса в качестве целевого объекта для разархивирования, если вы ожидаете, что в нем действительно что-то разархивируется (т. Е. Некоторое фактическое значение, отличное от null), это потому, что в качестве целевого объекта для разархивирования могут использоваться только пустые типы интерфейсов (если базовый динамический тип не выделен заранее).