我正在寻找一种简单的方法来测试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
答案 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不会导出,因此您必须比较字符串值。