上回聊到,golang 里面写一个简单的测试函数,和 benchmark 函数,如何检测测试代码覆盖度。 这回聊下如何编写 http server 测试代码。如果写过 API 服务的童鞋都知道。 测试服务端代码要先起个服务,再运行客户端代码。有没有办法和 go test 方法结合再一起,可以很快乐的编写服务端测试代码呢?
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
)
func main() {
// 启动一个测试服务
ts := httptest.NewServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
}))
defer ts.Close()
// 关键一步, 客户端完全使用标准套路,注意:url 使用 ts.URL 就行
res, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
greeting, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", greeting)
}
func TestShouldBindXML(t *testing.T) {
var d, d2 data
router := func() *gin.Engine {
router := gin.Default()
router.POST("/test.xml", func(c *gin.Context) {
var d3 data
err := c.ShouldBindXML(&d3)
assert.NoError(t, err)
c.XML(200, d3)
})
return router
}()
// 这里是 gin 和 http 标准库的区别,需要拿到 gin.Engine 的 ServeHTTP 函数
ts := httptest.NewServer( http.HandlerFunc(router.ServeHTTP))
defer ts.Close()
g := New(nil)
d.Id = 3
d.Data = "test data"
code := 200
err := g.POST(ts.URL + "/test.xml").SetXML(&d).BindXML(&d2).Code(&code).Do()
assert.NoError(t, err)
assert.Equal(t, code, 200)
assert.Equal(t, d, d2)
}
这个方法应用场景在编写一些库的时候会用到,只想模拟一个服务端跑 http handle 函数,里面可以设置 http header 等返回属性。然后客户端直接获得*http.Response 对象操作。可以理解为这是一个很薄薄的服务端测试写法
func TestHeaderDecode(t *testing.T) {
h := headerDecode{}
type tHeader struct {
Limit int `header:"limit"`
F64 float64 `header:"f64"`
F32 float32 `header:"f32"`
CreateTime time.Time `header:"createTime" time_format:"unixNano"`
UnixTime time.Time `header:"unixTime" time_format:"unix"`
Duration time.Duration `header:"duration"`
}
var theader tHeader
// 和正常的服务端回调函数一样
okFunc := func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("limit", "1000")
w.Header().Add("f64", "64")
w.Header().Add("f32", "32.1")
w.Header().Add("createTime", "1562400033000000123")
w.Header().Add("unixTime", "1562400033")
w.Header().Add("duration", "1h1s")
}
// 主要构造出 http.Request 对象
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
// 构造出 http.ResponseWriter 对象
w := httptest.NewRecorder()
//执行回调函数
okFunc(w, req)
//构造出*http.Response 对象
resp := w.Result()
// todo array slice
assert.NoError(t, h.Decode(resp, &theader))
}
1
richzhu 2019-09-18 11:42:47 +08:00
支持,谢谢分享
|
2
edward8628 2019-09-18 11:55:05 +08:00
感谢分享
|
3
guonaihong OP @richzhu 喜欢就好,后面我会把内容整理好,做成 gitbook,方便查看。
|
4
guonaihong OP @edward8628 喜欢就好。后面还会分享 go channel 相关技巧。
|