亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

http:閱讀已關閉的響應正文 - httptest.NewServer

http:閱讀已關閉的響應正文 - httptest.NewServer

Go
阿晨1998 2022-10-17 10:24:43
我正在嘗試使用 httptest.NewServer 進行測試,但遇到了障礙。在我的代碼中,我正在向外部 API 發出 GET 請求,并且我想使用 httptest.NewServer 對此進行測試。這是我發出請求的代碼(main.go):package mainimport (    "fmt"    "io"    "io/ioutil"    "log"    "net/http")type HTTPClient interface {    Do(req *http.Request) (*http.Response, error)}type NewRequest interface {    NewRequest(method string, url string, body io.Reader) (*http.Request, error)}var (    Client HTTPClient)func init() {    Client = &http.Client{}}func main() {    url := "https://httpbin.org/get"    GetData(url)}func GetData(url string) (*http.Response, error) {    req, err := http.NewRequest(http.MethodGet, url, nil)    if err != nil {        log.Fatalln(err)        return nil, err    }    resp, err := Client.Do(req)    if err != nil {        log.Fatalln(err)        return nil, err    }    defer resp.Body.Close()    responseBody, err := ioutil.ReadAll(resp.Body)    if err != nil {        log.Fatal(err)        return nil, err    }    fmt.Println(resp.Status)    fmt.Println(string(responseBody))    return resp, nil}當我運行它時,它工作正常。這是我的測試文件:package mainimport (    "fmt"    "io/ioutil"    "log"    "net/http"    "net/http/httptest"    "testing")func TestYourHTTPGet(t *testing.T){    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        fmt.Fprintln(w, `response from the mock server goes here`)    }))    defer ts.Close()    mockServerURL := ts.URL    resp, err := GetData(mockServerURL)    if err != nil {        fmt.Println("Error 1: ", err)    }    defer resp.Body.Close()    responseBody, err := ioutil.ReadAll(resp.Body)    if err != nil {        log.Fatal("Error 2: ", err)    }    fmt.Println(resp.Status)    fmt.Println(string(responseBody))}當我運行時,go test我收到錯誤:http: read on closed response body。如果我defer resp.Body.Close()從main.go測試中刪除正確通過。我不確定為什么會發生這種情況,并希望有人可以解釋這里發生了什么?
查看完整描述

2 回答

?
慕斯王

TA貢獻1864條經驗 獲得超2個贊

正如@Cerise Limón 所說,你打resp.Body.Close()了兩次電話,然后嘗試閱讀封閉的身體。要修復您的代碼,您可以從GetData函數中刪除主體處理并在外部執行GetData或返回主體而不在測試中讀取它。


main.go:


package main


import (

    "fmt"

    "io/ioutil"

    "log"

    "net/http"

)


var Client = &http.Client{}


func main() {

    url := "https://httpbin.org/get"


    status, data, err := GetData(url)

    if err != nil {

        log.Fatalln(err)

    }


    fmt.Println(status)

    fmt.Println(string(data))

}


func GetData(url string) (status string, body []byte, err error) {

    req, err := http.NewRequest(http.MethodGet, url, nil)

    if err != nil {

        return

    }


    resp, err := Client.Do(req)

    if err != nil {

        return

    }


    defer resp.Body.Close()


    body, err = ioutil.ReadAll(resp.Body)

    if err != nil {

        log.Fatalln(err)

    }


    return resp.Status, body, nil

}


main_test.go:


package main


import (

    "fmt"

    "net/http"

    "net/http/httptest"

    "testing"

)


func TestYourHTTPGet(t *testing.T){

    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        fmt.Fprintln(w, `response from the mock server goes here`)

    }))

    defer ts.Close()


    mockServerURL := ts.URL


    status, data, err := GetData(mockServerURL)

    if err != nil {

        fmt.Println("Error 1: ", err)

    }


    fmt.Println(status)

    fmt.Println(string(data))

}


查看完整回答
反對 回復 2022-10-17
?
蝴蝶不菲

TA貢獻1810條經驗 獲得超4個贊

GetData()的 return 是一個指針。你跑GetData()進去main.go,retun時,它會關閉resp.body。如果你再讀一遍,它會導致http: read on closed response body

所以如果你想再次閱讀正文,你不應該返回*http.Response,你應該克隆resp.body返回


查看完整回答
反對 回復 2022-10-17
  • 2 回答
  • 0 關注
  • 126 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號