2017-04-19 98 views
2

我正在为GoLang中的简单REST服务编写测试。但是,因为我使用julienschmidt/httprouter作为路由库。我正在努力如何编写测试。如何使用httprouter编写测试

main.go

package main 

func main() { 
    router := httprouter.New() 
    bookController := controllers.NewBookController() 
    router.GET("/book/:id", bookController.GetBook) 
    http.ListenAndServe(":8080", router) 
} 

控制器

package controllers 

type BookController struct {} 

func NewBookController *BookController { 
    return &BookController() 
} 

func (bc BookController) GetBook(w http.ResponseWriter, r *http.Request, p httprouter.Params) { 
    fmt.Fprintf(w,"%s", p) 
} 

我的问题是:如何测试这一点的同时GetBook既不是HttpHandler的,也不HttpHandle

如果我使用的是传统的处理程序,测试会很容易喜欢这个

func TestGetBook(t *testing.T) { 
    req, _ := http.NewRequest("GET", "/book/sampleid", nil) 
    rr := httptest.NewRecorder() 
    handler := controllers.NewBookController().GetBook 
    handler.ServeHTTP(rr,req) 
    if status := rr.code; status != http.StatusOK { 
    t.Errorf("Wrong status") 
    } 
} 

问题是,httprouter不是handler或handlefunc。所以我现在坚持

+0

大......我是这么认为的,但总是最好仔细检查:) – Flimzy

回答

3

只需旋转了一个新的路由器为每一个测试,然后注册测试下的处理程序,然后通过测试请求路由器,而不是处理程序,使路由器可以解析路径参数和通他们到处理程序。

func TestGetBook(t *testing.T) { 
    handler := controllers.NewBookController() 
    router := httprouter.New() 
    router.GET("/book/:id", handler.GetBook) 

    req, _ := http.NewRequest("GET", "/book/sampleid", nil) 
    rr := httptest.NewRecorder() 

    router.ServeHTTP(rr, req) 
    if status := rr.code; status != http.StatusOK { 
     t.Errorf("Wrong status") 
    } 
} 
+0

感谢。这对我有用。但是,你认为是否有另一种方法可以使测试代码更易于编写?也许修改软件包主要? – JSNoob

+0

取决于你在这个测试中难以写的东西......如果你有很多这样的'TestXxx'函数来测试不同的处理程序,并且你觉得你正在重复自己,你可以将重复代码提取到一个函数中并在你的测试中使用它。例如。你可以有一个函数,我们称之为'testrouter',它创建一个新的路由器,注册每个处理器,然后返回路由器,并且可以直接将'rr'和'req'传递给它的结果,就像'testrouter() .ServeHTTP(rr,req)'... – mkopriva

+1

如果你想测试一个具有许多不同请求的处理器,请看[表驱动测试](https://github.com/golang/go/wiki/TableDrivenTests )。 – mkopriva

0

你需要用你的处理程序,以便它可以作为一个http.HandlerFunc访问:

func TestGetBook(t *testing.T) { 
    req, _ := http.NewRequest("GET", "/book/sampleid", nil) 
    rr := httptest.NewRecorder() 
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     controllers.NewBookController().GetBook(w, r, httprouter.Params{}) 
    }) 
    handler.ServeHTTP(rr,req) 
    if status := rr.code; status != http.StatusOK { 
     t.Errorf("Wrong status") 
    } 
} 

如果处理程序需要的参数,你要么必须从请求手动解析它们,或者只是提供他们作为第三个参数。