英文:
How to write test with httprouter
问题
我正在为GoLang中的一个简单REST服务编写测试。但是,由于我在使用julienschmidt/httprouter作为路由库,我在如何编写测试方面遇到了困难。
main.go
package main
func main() {
router := httprouter.New()
bookController := controllers.NewBookController()
router.GET("/book/:id", bookController.GetBook)
http.ListenAndServe(":8080", router)
}
controllers
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既不是处理程序也不是handlefunc。所以我现在陷入了困境。
英文:
I am writing tests for a simple REST service in GoLang. But, because I am using julienschmidt/httprouter as the routing library. I am struggling on how to write test.
main.go
package main
func main() {
router := httprouter.New()
bookController := controllers.NewBookController()
router.GET("/book/:id", bookController.GetBook)
http.ListenAndServe(":8080", router)
}
controllers
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)
}
My question is: How can test this while GetBook is neither HttpHandler nor HttpHandle
If I use a traditional handler, the test will be easy like this
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")
}
}
The problem is, httprouter is not handler, or handlefunc. So I am stuck now
答案1
得分: 16
为每个测试启动一个新的路由器,然后在测试下注册处理程序,然后将测试请求传递给路由器,而不是处理程序,以便路由器可以解析路径参数并将它们传递给处理程序。
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")
}
}
请注意,这是一个示例代码片段,用于测试获取书籍的处理程序。在测试中,我们创建了一个新的路由器和处理程序,并发送一个GET请求到/book/sampleid
路径。然后,我们检查响应的状态码是否为200(http.StatusOK)。
英文:
Just spin up a new router for each test and then register the handler under test, then pass the test request to the router, not the handler, so that the router can parse the path parameters and pass them to the handler.
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")
}
}
答案2
得分: 3
你需要将你的处理程序包装起来,以便可以将其作为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")
}
}
如果你的处理程序需要参数,你可以手动从请求中解析它们,或者将它们作为第三个参数提供。
英文:
You need to wrap your handler so that it can be accessed as an 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")
}
}
If your handler requires parameters, you'll either have to parse them manually from the request, or just supply them as the third argument.
答案3
得分: 1
你可以尝试在不使用ServeHTTP
的情况下进行以下操作:
func TestGetBook(t *testing.T) {
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
w := httptest.NewRecorder()
controllers.NewBookController().GetBook(w, req, []httprouter.Param{{Key: "id", Value: "101"}})
resp := w.Result()
body, _ := ioutil.ReadAll(resp.Body)
t.Log(resp.StatusCode)
t.Log(resp.Header.Get("Content-Type"))
t.Log(string(body))
}
这段代码用于测试获取书籍信息的功能。它创建了一个模拟的HTTP请求,并将其发送到http://example.com/foo
。然后,它调用controllers.NewBookController().GetBook
方法来处理该请求,并将结果写入w
(一个httptest.ResponseRecorder
对象)。最后,它从响应中读取状态码、Content-Type头和响应体,并将它们记录到测试日志中。
英文:
u can try this without ServeHTTP
func TestGetBook(t *testing.T) {
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
w := httptest.NewRecorder()
controllers.NewBookController().GetBook(w, req, []httprouter.Param{{Key: "id", Value: "101"}})
resp := w.Result()
body, _ := ioutil.ReadAll(resp.Body)
t.Log(resp.StatusCode)
t.Log(resp.Header.Get("Content-Type"))
t.Log(string(body))
}
答案4
得分: -1
这是另一个很好的博客和相应的工作代码:
https://github.com/gsingharoy/httprouter-tutorial/blob/master/part4/handlers_test.go
英文:
here is one more good blog and corresponding working code for this:
> https://medium.com/@gauravsingharoy/build-your-first-api-server-with-httprouter-in-golang-732b7b01f6ab
>
> https://github.com/gsingharoy/httprouter-tutorial/blob/master/part4/handlers_test.go
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论