How to write a test using httprouter

I am writing tests for a simple REST service in GoLang. But since I am using julienschmidt / httprouter as my routing library. I am struggling on how to write a 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 to check this while GetBook is neither HttpHandler nor HttpHandle

If I use a traditional handler, the test is as simple as 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 that httprouter is not a handler or handlefunc. So I'm stuck now

+3


source to share


4 answers


Just start a new router for each test, and then register a handler in the test, and then pass the test request to the router, not the handler, so the router can parse the path parameters and pass them on 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")
    }
}

      

+5


source


You need to wrap the handler so that it can be accessed like 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 will either have to manually parse it from the request, or simply supply it as the third argument.

0


source


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

      

0


source


-1


source







All Articles