V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
guonaihong
V2EX  ›  Go 编程语言

go test 常见套路(2)

  •  
  •   guonaihong ·
    guonaihong · 2019-09-18 08:55:15 +08:00 · 2412 次点击
    这是一个创建于 1680 天前的主题,其中的信息可能已经有所发展或是发生改变。

    上回聊到,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)
    }
    

    gin 框架测试代码

    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)
    }
    
    

    基于 func(w http.ResponseWriter, r *http.Request) 编写测试代码

    这个方法应用场景在编写一些库的时候会用到,只想模拟一个服务端跑 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))
    
    }
    
    

    我的 github 地址

    https://github.com/guonaihong/gout

    4 条回复    2019-09-18 12:47:53 +08:00
    richzhu
        1
    richzhu  
       2019-09-18 11:42:47 +08:00
    支持,谢谢分享
    edward8628
        2
    edward8628  
       2019-09-18 11:55:05 +08:00
    感谢分享
    guonaihong
        3
    guonaihong  
    OP
       2019-09-18 12:46:34 +08:00
    @richzhu 喜欢就好,后面我会把内容整理好,做成 gitbook,方便查看。
    guonaihong
        4
    guonaihong  
    OP
       2019-09-18 12:47:53 +08:00
    @edward8628 喜欢就好。后面还会分享 go channel 相关技巧。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5732 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 06:29 · PVG 14:29 · LAX 23:29 · JFK 02:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.