httptest - HTTP 测试辅助工具
本节我们通过一个社区帖子的增删改查的例子来学习该包。
我们首先构建一个简单的 Web 应用。
为了简单起见,数据保存在内存,并且没有考虑并发问题。
对于 Topic
的增删改查代码很简单,可以查看。
接下来,是通过 net/http
包来实现一个 Web 应用。
func main() {
http.HandleFunc("/topic/", handleRequest)
http.ListenAndServe(":2017", nil)
}
...
/topic/
开头的请求都交由 handleRequest
处理,它根据不同的 Method
执行相应的增删改查,详细代码可以查看 server.go。
准备好 Web 应用后,我们启动它。
通过 curl
进行简单的测试:
增:curl -i -X POST -H ‘content-type: application/json’ -d ‘{“title”:”The Go Standard Library”,”content”:”It contains many packages.”}’
查:curl -i -X GET http://localhost:2017/topic/1
改:curl -i -X PUT -H ‘content-type: application/json’ -d ‘{“title”:”The Go Standard Library By Example”,”content”:”It contains many packages, enjoying it.”}’
删:curl -i -X DELETE http://localhost:2017/topic/1
上面,我们通过 curl
对我们的 Web 应用的接口进行了测试。现在,我们通过 net/http/httptest
包进行测试。
我们先测试创建帖子,也就是测试 handlePost
函数。
func TestHandlePost(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("/topic/", handleRequest)
reader := strings.NewReader(`{"title":"The Go Standard Library","content":"It contains many packages."}`)
r, _ := http.NewRequest(http.MethodPost, "/topic/", reader)
w := httptest.NewRecorder()
mux.ServeHTTP(w, r)
if resp.StatusCode != http.StatusOK {
t.Errorf("Response code is %v", resp.StatusCode)
}
因为 handlePost
的函数签名是 func handlePost(w http.ResponseWriter, r *http.Request) error
,为了测试它,我们必须创建 http.ResponseWriter
和 http.Request
的实例。
接下来的代码就是创建一个 http.Request
实例 和一个 http.ResponseWriter
的实例。这里的关键是,通过 httptest.NewRecorder()
可以获得 httptest.ResponseRecorder
结构,而此结构实现了http.ResponseWriter
接口。
reader := strings.NewReader(`{"title":"The Go Standard Library","content":"It contains many packages."}`)
r, _ := http.NewRequest(http.MethodPost, "/topic/", reader)
w := httptest.NewRecorder()
准备好之后,可以测试目标函数了。这里,我们没有直接调用 handlePost(w, r)
,而是调用 mux.ServeHTTP(w, r)
,实际上这里直接调用 handlePost(w, r)
也是可以的,但调用 mux.ServeHTTP(w, r)
会更完整地测试整个流程。mux.ServeHTTP(w, r)
最终也会调用到 handlePost(w, r)
。
最后,通过 go test -v
运行测试。
查、改和删帖子的接口测试代码类似,比如,handleGet
的测试代码如下:
func TestHandleGet(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("/topic/", handleRequest)
w := httptest.NewRecorder()
mux.ServeHTTP(w, r)
resp := w.Result()
if resp.StatusCode != http.StatusOK {
}
topic := new(Topic)
json.Unmarshal(w.Body.Bytes(), topic)
if topic.Id != 1 {
t.Errorf("Cannot get topic")
}
}
注意:因为数据没有落地存储,为了保证后面的测试正常,请将 TestHandlePost
放在最前面。
细心的朋友应该会发现,上面的测试代码有重复,比如:
w := httptest.NewRecorder()
这正好是前面学习的 setup
可以做的事情,因此可以使用 TestMain
来做重构。
var w *httptest.ResponseRecorder
func TestMain(m *testing.M) {
http.DefaultServeMux.HandleFunc("/topic/", handleRequest)
w = httptest.NewRecorder()
os.Exit(m.Run())
导航
- 上一节:testing - 其他功能
- 下一节: