martins
martins

Reputation: 10009

Why aren't my request URL parsed correct when I use http.NewRequest for tests?

When I test my /health/ endpoint using curl, everything works as expected: curl localhost:8080/health/my_id returns my_id.

But when I run my test the handler isn't able to extract the ID from the params. How am I supposed to craft my query from the tests to achieve that?

HealthTest

 12 func TestHealth(t *testing.T) {
 13
 14         // Initialize a new httptest.ResponseRecorder.
 15         rr := httptest.NewRecorder()
 16
 17         // Initialize a new dummy http.Request.
 18         r, err := http.NewRequest(http.MethodGet, "/health/my_id", nil)
 19         if err != nil {
 20                 t.Fatal(err)
 21         }
 22
 23         // Call the handler function, passing in the
 24         // httptest.ResponseRecorder and http.Request.
 25         handler.HandleHealth(rr, r)
 26
 27         // Call the Result() method on the http.ResponseRecorder to get the
 28         // http.Response generated by the handler.
 29         rs := rr.Result()
 30
 31         // We can then examine the http.Response to check that the status code // written by the handler was 200.
 32         if rs.StatusCode != http.StatusOK {
 33                 t.Errorf("want %d; got %d", http.StatusOK, rs.StatusCode)
 34         }
 35
 36         // And we can check that the response body written by the handler
 37         defer rs.Body.Close()
 38         body, err := ioutil.ReadAll(rs.Body)
 39         if err != nil {
 40                 t.Fatal(err)
 41         }
 42
 43         want := "my_id"
 44         got := string(body)
 45         if got != want {
 46                 t.Errorf("want body to equal %q. Got: %q", want, got)
 47         }
 48 }

Running that test results in:

internal/handler/health/handler_test.go|46| want body to equal "my_id". Got: ""

HealthHandlers

   23 func (h *Handler) HandleHealth(w http.ResponseWriter, r *http.Request) {
   24         id := chi.URLParam(r, "id")
   25         log.Println("ID: ", id)
   26         render.PlainText(w, r, id)
   27 }
   28

   29 func RegisterRoutes(router *chi.Mux, handler *Handler) {
   30         router.Get("/health/{id}", handler.HandleHealth)
   31 }

Upvotes: 0

Views: 153

Answers (1)

Jonathan Hall
Jonathan Hall

Reputation: 79546

The chi library is what handles your wildcard URLs. But you're bypassing chi in your tests by calling HandleHealth directly.

If you want chi to process the request against the wildcard provided in your RegisterRoutes method, you obviously need to actually call RegisterRoutes in your test.

Doing so requires changing your test structure slightly. Rather than:

    handler.HandleHealth(rr, r)

You'll need something like:

    chi := chi.NewMux()
    RegisterRoutes(chi, handler)
    chi.ServeHTTP(rr, r)

Upvotes: 1

Related Questions