测试http.Response.Body已关闭

时间:2019-06-23 12:26:02

标签: http go

我正在寻找一种简单的方法来测试http.Response.Body.Close()是否被调用。

我已经通过计算与服务器的开放连接数(https://golang.org/src/net/http/serve_test.go-countCloseListener)进行了尝试,但似乎只有通过重写Roundtripper才能在客户端进行测试。

因此,下面的示例有效,但我想知道是否有更简单的方法来完成这种常见任务...

package closing

import "net/http"

type MyClient struct {
    Client http.Client
}

func (c *MyClient) Closing() (err error) {
    res, err := c.Client.Get("http://localhost")
    defer res.Body.Close()
    return
}

func (c *MyClient) NotClosing() (err error) {
    _, err = c.Client.Get("http://localhost")
    return
}

https://github.com/elgohr/golang-test-body-close/blob/master/performsHttpRequest.go

package closing_test

import (
    "github.com/elgohr/closing"
    "io"
    "io/ioutil"
    "net/http"
    "strings"
    "testing"
)

func TestShouldBeClosedWhenClosed(t *testing.T) {
    tripper := NewFakeRoundTripper()
    cl := closing.MyClient{
        Client: http.Client{
            Transport: tripper,
        },
    }

    if err := cl.Closing(); err != nil {
        t.Error(err)
    }

    if !tripper.Body.Closed {
        t.Error("Should be closed, but wasn't")
    }
}

func TestShouldBeOpenWhenNotClosed(t *testing.T) {
    tripper := NewFakeRoundTripper()
    cl := closing.MyClient{
        Client: http.Client{
            Transport: tripper,
        },
    }

    if err := cl.NotClosing(); err != nil {
        t.Error(err)
    }

    if tripper.Body.Closed {
        t.Error("Should be open, but wasn't")
    }
}

func NewFakeRoundTripper() *FakeRoundTripper {
    return &FakeRoundTripper{
        Body: &FakeReadCloser{
            ReadCloser: ioutil.NopCloser(strings.NewReader("content")),
        },
    }
}

type FakeRoundTripper struct {
    Body *FakeReadCloser
}

func (r *FakeRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
    return &http.Response{
        Body: r.Body,
    }, nil
}

type FakeReadCloser struct {
    io.ReadCloser
    Closed bool
}

func (r *FakeReadCloser) Close() error {
    r.Closed = true
    return r.ReadCloser.Close()
}

https://github.com/elgohr/golang-test-body-close/blob/master/performsHttpRequest_test.go

1 个答案:

答案 0 :(得分:0)

尝试从身体读取以测试其是否关闭。

r, err := http.Get("http://google.com")
r.Body.Close()

_, err = r.Body.Read(nil)
if err == nil {
  // can still read from body so it's not closed

} else if err != nil && err.Error() == "http: read on closed response body" {
  // body is already closed
} 

很遗憾,返回的错误errReadOnClosedResBody不会导出,因此您必须比较字符串值。