Q:对于web的api接口如何有效的进行自测?
最偷懒的说法就是,”喂,前端开发,你页面做好了没?能不能调试下我的这个接口?“。没错,很大一部分同学是不进行自测的,都会拖到和前端进行联调的时候再测试,然后代码质量不佳的情况下,就会浪费很多联调时间
当然也有同学会说,我没这么low,我有postman,我会自己进行调试,确保提供给客户端使用联调的时候是正确的。没错,postman是个好工具,可以视图话的访问接口,甚至和很多测试平台继承进行持久化自动测试用例测试。但是你还得找个环境部署你的项目,当然本地直接启动调试服务也行。
但是我这边想介绍的是Go自带的httptest包,可以更方便的在本地开发环境下进行测试,不需要启动你的web服务就能测试
一个简单的demo
main.go:一个再简单不过的基于http包创建的web服务,提供了一个hello接口
package main
func initHttpHandler() {
http.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request){
response, _ := json.Marshal(map[string]string{
"userId": req.URL.Query().Get("userId"),
"name": req.PostFormValue("name"),
})
w.Write(response)
})
}
func main() {
initHttpHandler()
http.ListenAndServe(":8080", nil)
}
# 启动web服务
go run main.go
# 进行接口调试
curl "http://127.0.0.1:8080/hello?userId=123" -d "name=zhangsan" # {"name":"zhangsan","userId":"123"}
现在,介绍如何利用httptest来避开服务的启动和curl进行测试
编写一个标准的测试用力,main_test.go:
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestHttptest(t *testing.T) {
initHttpHandler()
w := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/hello?userId=123", strings.NewReader("name=zhangsan"))
req.Header.Set("Content-type", "application/x-www-form-urlencoded")
http.DefaultServeMux.ServeHTTP(w, req)
fmt.Println(string(w.Body.Bytes()))
}
# 执行测试用例
go test
{"name":"zhangsan","userId":"123"}
PASS
我们并没有启动这个http的服务,直接利用了 http.DefaultServMux 这个http默认的handler来处理请求,看过http包的源码的同学应该很能理解,http.ListenAndServe 启动的时候,如果没有指定第二个参数handler,那么最终用的就是这个 DefaultServMux hanlder
同理,其他web框架比如Gin,也可以利用httptest进行单元测试,简易版main_test.go如下:
func TestHttptest(t *testing.T) {
r := gin.Default()
r.POST("/hello", func(c *gin.Context){
userId := c.Query("userId")
name := c.PostForm("name")
c.JSON(http.StatusOK, gin.H{"userId":userId, "name":name})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/hello?userId=123", strings.NewReader("name=zhangsan"))
req.Header.Set("Content-type", "application/x-www-form-urlencoded")
r.ServeHTTP(w, req)
fmt.Println(string(w.Body.Bytes()))
}