Test with httprouter
continuous-integration/drone/push Build is passing Details

main
Drew Bednar 4 weeks ago
parent ec1a4feb74
commit af6be5d621

@ -3,6 +3,9 @@ package main
import (
"fmt"
"net/http"
"strconv"
"github.com/julienschmidt/httprouter"
)
func (app *application) createMovieHandler(w http.ResponseWriter, r *http.Request) {
@ -10,8 +13,21 @@ func (app *application) createMovieHandler(w http.ResponseWriter, r *http.Reques
fmt.Fprintln(w, "Resource created")
}
func (app *application) getAllMoviesHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Movies List")
func (app *application) getMovieHandler(w http.ResponseWriter, r *http.Request) {
// When httprouter is parsing a request, any interpolated URL parameters will be
// stored in the request context. We can use the ParamsFromContext() function to
// retrieve a slice containing these parameter names and values.
params := httprouter.ParamsFromContext(r.Context())
id, err := strconv.ParseInt(params.ByName("id"), 10, 64)
if err != nil || id < 1 {
http.NotFound(w, r)
return
}
app.logger.Debug((fmt.Sprintf("Using id: %d", id)))
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "show the details of movie %d\n", id)
}
func (app *application) healthCheckHandler(w http.ResponseWriter, r *http.Request) {

@ -2,6 +2,7 @@ package main
import (
"bytes"
"fmt"
"io"
"log/slog"
"net/http"
@ -25,8 +26,7 @@ func TestHealthRoute(t *testing.T) {
}
app := newTestApplication()
health := http.HandlerFunc(app.healthCheckHandler)
health.ServeHTTP(respRec, r)
app.routes().ServeHTTP(respRec, r)
resp := respRec.Result()
@ -56,8 +56,7 @@ func TestCreateMovieHandler(t *testing.T) {
}
app := newTestApplication()
movie := http.HandlerFunc(app.createMovieHandler)
movie.ServeHTTP(respRec, r)
app.routes().ServeHTTP(respRec, r)
resp := respRec.Result()
@ -78,32 +77,49 @@ func TestCreateMovieHandler(t *testing.T) {
}
func TestGetAllMoviesHandler(t *testing.T) {
respRec := httptest.NewRecorder()
want := "Movies List"
r, err := http.NewRequest(http.MethodGet, "/v1/movies", nil)
if err != nil {
t.Fatal(err)
}
app := newTestApplication()
movie := http.HandlerFunc(app.getAllMoviesHandler)
movie.ServeHTTP(respRec, r)
resp := respRec.Result()
if resp.StatusCode != http.StatusOK {
t.Fatalf("Got status code %q, wanted status code %q", resp.StatusCode, http.StatusOK)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
testTable := []struct {
name string
id string
wantCode int
useID bool
}{
{
name: "Get Movie By ID",
id: "1337",
wantCode: 200,
},
{
name: "No ID provided",
id: "",
wantCode: 404,
},
{
name: "Negative ID",
id: "-1",
wantCode: 404,
},
}
body = bytes.TrimSpace(body)
if !strings.Contains(string(body), want) {
t.Fatalf("Did not find: %q in response body", want)
for _, test := range testTable {
t.Run(test.name, func(t *testing.T) {
respRec := httptest.NewRecorder()
r, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/v1/movies/%s", test.id), nil)
t.Logf("Path: %s, Method: %s", r.URL.Path, r.Method)
if err != nil {
t.Fatal(err)
}
app := newTestApplication()
// want to test with httprouter since we use it to parse context
app.routes().ServeHTTP(respRec, r)
resp := respRec.Result()
t.Logf("Code: %d", resp.StatusCode)
if resp.StatusCode != test.wantCode {
t.Fatalf("Got status code '%d', wanted status code '%d'", resp.StatusCode, test.wantCode)
}
})
}
}

@ -7,11 +7,15 @@ import (
)
func (app *application) routes() http.Handler {
// The httprouter package also provides a router.Handler()
// method which you can use when you want to register a regular
// http.Handler rather than handler functions as seen below
router := httprouter.New()
router.HandlerFunc(http.MethodGet, "/v1/healthcheck", app.healthCheckHandler)
router.HandlerFunc(http.MethodPost, "/v1/movies", app.createMovieHandler)
router.HandlerFunc(http.MethodGet, "/v1/movies", app.getAllMoviesHandler)
router.HandlerFunc(http.MethodGet, "/v1/movies/:id", app.getMovieHandler)
return router
}

Loading…
Cancel
Save