2016-11-18 115 views
2

我有类似下面的一组请求处理程序:如何测试Golang中的http请求处理程序?

func GetProductsHandler(w http.ResponseWriter, req *http.Request) { 
    defer req.Body.Close() 
    products := db.GetProducts() 

    // ... 
    // return products as JSON array 
} 

如何测试他们以正确的方式?我应该将模拟的ResponseWriter和Request对象发送给函数并查看结果吗?

是否有工具可以在Go中模拟请求和响应对象以简化流程,而无需在测试之前启动服务器?

+3

你的意思是['httptest' package](https://golang.org/pkg/net/http/httptest/)? – JimB

+0

'http.Request'和'http.Response'都是简单的和“完全导出”的类型,所以只需将它们设置为任何你想要或需要的。不需要工具或“嘲笑”。 – Volker

+0

https://golang.org/pkg/net/http/httptest/#example_ResponseRecorder – dm03514

回答

3

Go提供了一个用于测试处理程序的模拟编写器。标准库文档提供了一个例子:

package main 

import (
    "fmt" 
    "net/http" 
    "net/http/httptest" 
) 

func main() { 
    handler := func(w http.ResponseWriter, r *http.Request) { 
     http.Error(w, "something failed", http.StatusInternalServerError) 
    } 

    req := httptest.NewRequest("GET", "http://example.com/foo", nil) 
    w := httptest.NewRecorder() 
    handler(w, req) 

    fmt.Printf("%d - %s", w.Code, w.Body.String()) 
} 

我认为有一个全局依赖(db)抛出一个扳手插入干净的单元测试。使用去你的测试可以重新分配一个值,掩盖,全球价值db

另一种策略(我的首选)是打包处理的结构,其中有一个db属性..

type Handlers struct { 
    db DB_INTERFACE 
} 

func (hs *Handlers) GetProductsHandler(w http.ResponseWriter, req *http.Request) {...} 

这样,你的测试实例化一个Handlers与存根db对象,这将使你创建IO免费单元测试。

+0

答案中提到的“标准库文档”可以在这里找到:https://golang.org/pkg/net/http/ httptest / – Adrian