Почему мой URL-адрес запроса не обрабатывается правильно, когда я использую http.NewRequest для тестов?

#go #testing

#Вперед #тестирование

Вопрос:

Когда я тестирую свою / health / endpoint с помощью curl, все работает так, как ожидалось: curl localhost:8080/health/my_id возвращает my_id .

Но когда я запускаю свой тест, обработчик не может извлечь идентификатор из параметров. Как я должен обработать свой запрос из тестов, чтобы достичь этого?

Проверка работоспособности

  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 }
  

Выполнение этого теста приводит к:

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

Обработчики работоспособности

    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 }
  

Комментарии:

1. Также не имеет отношения к вашему вопросу, но пара советов: для тестов используйте httptest.NewRequest() вместо http.NewRequest() . Кроме того, это не «фиктивный» запрос. Это настоящий, на 100% подлинный, полноценный, обычный запрос.

Ответ №1:

Библиотека chi обрабатывает ваши подстановочные URL-адреса. Но вы обходите chi в своих тестах, вызывая HandleHealth напрямую.

Если вы хотите, чтобы chi обрабатывал запрос с использованием подстановочного знака, указанного в вашем RegisterRoutes методе, вам, очевидно, нужно на самом деле вызвать RegisterRoutes свой тест.

Для этого требуется немного изменить структуру вашего теста. Вместо:

     handler.HandleHealth(rr, r)
  

Вам понадобится что-то вроде:

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