'in tests mux.Vars() returns nil instead of expected map
I have a Gorilla Mux router setup inside a function that returns *mux.Router
, goes like this
func MakeApp(services service.Service, pe PolicyEnforce) *mux.Router {
app := mux.NewRouter()
app.NotFoundHandler = &NotFound{}
app.Use(token.TokenMiddleware)
# ...
app.Methods(http.MethodPost).Path("/api/v1/subscription/{emisor}/mh").HandlerFunc(MakeUpdateMH(services, pe))
app.Methods(http.MethodGet).Path("/api/v1/subscription/{emisor}/mh").HandlerFunc(MakeGetMH(services, pe))
app.Methods(http.MethodPost).Path("/api/v1/subscription").HandlerFunc(MakeCreateSubscription(services, pe))
app.Methods(http.MethodGet).Path("/api/v1/subscription/{emisor}").HandlerFunc(MakeGetSubscription(services, pe))
# ...
return app
}
So, on my tests I prepare the handle with an URL and run it:
func (suite *AppTestSuite) TestUpdateMH() {
args := &service.UpdateMHInput{
Usuario: new(string),
Clave: new(string),
Pin: new(string),
Certificado: new(string),
Actividades: []string{},
}
reader, err := makeBody(args)
suite.NoError(err)
handle := token.TokenMiddleware(transport.MakeUpdateMH(suite._s, suite.pe))
req := httptest.NewRequest(http.MethodPut, "/api/v1/subscription/-/mh", reader)
w := httptest.NewRecorder()
t := genToken([]v43.Rol{
{
Nombre: "mh",
Permisos: []v43.Permiso{{
Sujeto: permission.MHCredentials,
Accion: permission.Update,
}},
},
})
req.Header.Add("Authorization", t)
// configura repository
suite.r.On("UpdateIssuerMH", emisor, args.Usuario, args.Clave, args.Pin, args.Certificado, args.Actividades).Return(v43.Grupo{}, nil)
handle.ServeHTTP(w, req)
resp := w.Result()
suite.Equal(http.StatusOK, resp.StatusCode, resp.Status)
}
Inside the handle things look like this:
func MakeUpdateMH(s service.Service, p PolicyEnforce) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
emisor := mux.Vars(r)["emisor"]
// revisa permisos
permitido := p.TienePermiso(r.Context(), permission.MHCredentials, permission.Update) && p.PuedeActuarSobreEmisor(r.Context(), emisor)
if !permitido {
reportError(w, fault.ErrPermissionDenied, http.StatusForbidden, fault.MessageForbidden, fault.MessageForbidden)
return
}
// cambia el emisor afectado por aquel obtenido de la URL
if emisor != "-" || emisor == "" {
emisor = token.GetSub(r.Context())
}
var input service.UpdateMHInput
dec := json.NewDecoder(r.Body)
err := dec.Decode(&input)
if err != nil {
http.Error(w, fault.NewBackendError("no se pudo decodificar solicitud: %v", err).Error(), http.StatusBadRequest)
return
}
output, err := s.UpdateMHCredentials(emisor, input.Usuario, input.Clave, input.Pin, input.Certificado, input.Actividades)
if err != nil {
http.Error(w, fault.NewBackendError("Error al actualizar credenciales de MH: %v", err).Error(), http.StatusInternalServerError)
return
}
enc := json.NewEncoder(w)
enc.Encode(output)
}
}
and I've noticed that mux.Vars(r)
is returning nil
instead of the map of values, which should contain {"emisor": "-"}
and I cannot understand why this is not the case.
I'm already handling the case for when "emisor"
is empty, but for other routers where "-" or empty string cannot be used this quirk is causing me troubles, what am I doing wrong, and how can I still run my tests successfully without having to manually inject my Vars? and also: will this issue translate into production?
Solution 1:[1]
My setup is wrong, I'm not using *mux.Router
in my tests but calling the handlers directly. If I wanted to use the *mux.Router
returned by my function MakeApp
then I'll need to put that inside a test HTTP server using net/http/httptest
.
Solution 2:[2]
If you're creating a request that you're not routing but you still want the Vars, there's another option.
router := mux.NewRouter()
... // setup your routes
var match mux.RouteMatch
success := router.Match(req, &match)
if success {
id := match.Vars["id"]
...
}
This is equivalent to router.ServeHTTP(req, res)
in how it'll prep the variables except it doesn't actually execute the handler. The match
object also has more information about the route that the request would hit.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | shackra |
Solution 2 | Corey Ogburn |