1

I am writing the unit test case for my http APIs, i need to pass the path param to the API endpoint

GetProduct(w http.ResponseWriter, r *http.Request) {
    uuidString := chi.URLParam(r, "uuid")
    uuid1, err := uuid.FromString(uuidString)
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        _, _ = w.Write([]byte(err.Error()))
        return
    }
}

I need to test this method and for that i need to pass a valid uuid to r http.Request, please suggest how can i do that, I tried a few options from my test class like

req.URL.Query().Set("uuid", "valid_uuid") 

But it did not work. How can I test this method by passing a valid uuid to request?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Anshul Sharma
  • 1,018
  • 3
  • 17
  • 39
  • 1
    Never used `go-chi` as I always used `gorilla`. BTW, in this answer you should find the solution to your question: https://stackoverflow.com/a/70719412/14394371 If you're open to switch to `gorilla` I can provide you a complete example! – ossan Dec 23 '22 at 16:14
  • 1
    @IvanPesenti Please suggest that gorilla solution. – Anshul Sharma Dec 23 '22 at 16:21
  • What does "But it did not work" mean? What error or other unexpected behavior did you see? – Jonathan Hall Dec 23 '22 at 16:33

1 Answers1

3

Let me present my usual solution with gorilla package.

handler.go file

package httpunittest

import (
    "net/http"

    "github.com/gorilla/mux"
)

func GetProduct(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    uuidString, isFound := params["uuid"]
    if !isFound {
        w.WriteHeader(http.StatusBadRequest)
        return
    }
    w.Write([]byte(uuidString))
}

Here, you use the function Vars to fetch all of the URL parameters present within the http.Request. Then, you've to look for the uuid key and do your business logic with it.

handler_test.go file

package httpunittest

import (
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/gorilla/mux"
    "github.com/stretchr/testify/assert"
)

func TestGetProduct(t *testing.T) {
    t.Run("WithUUID", func(t *testing.T) {
        r := httptest.NewRequest(http.MethodGet, "/products/1", nil) // note that this URL is useless
        r = mux.SetURLVars(r, map[string]string{"uuid": "1"})
        w := httptest.NewRecorder()

        GetProduct(w, r)

        assert.Equal(t, http.StatusOK, w.Result().StatusCode)
    })

    t.Run("Without_UUID", func(t *testing.T) {
        r := httptest.NewRequest(http.MethodGet, "/products", nil) // note that this URL is useless
        w := httptest.NewRecorder()

        GetProduct(w, r)

        assert.Equal(t, http.StatusBadRequest, w.Result().StatusCode)
    })
}

First, I used the functions provided by the httptest package of the Go Standard Library that fits well for unit testing our HTTP handlers.
Then, I used the function SetUrlVars provided by the gorilla package that allows us to set the URL parameters of an http.Request.
Thanks to this you should be able to achieve what you need!

ossan
  • 1,665
  • 4
  • 10