问题描述
我在一个返回 *mux.Router
的函数中设置了一个 Gorilla Mux 路由器,就像这样
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
}
所以,在我的测试中,我准备了一个带有 URL 的句柄并运行它:
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)
}
手柄内部看起来像这样:
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",http.StatusInternalServerError)
return
}
enc := json.NewEncoder(w)
enc.Encode(output)
}
}
我注意到 mux.Vars(r)
返回的是 nil
而不是值的映射,它应该包含 {"emisor": "-"}
,我不明白为什么不是这样。
我已经在处理 "emisor"
为空时的情况,但是对于不能使用“-”或空字符串的其他路由器,这个怪癖给我带来了麻烦,我做错了什么,以及如何在无需手动注入 Vars 的情况下仍然成功运行测试? 以及:这个问题会转化为生产吗?
解决方法
我的设置有误,我没有在测试中使用 *mux.Router
,而是直接调用处理程序。如果我想使用我的函数 *mux.Router
返回的 MakeApp
,那么我需要使用 net/http/httptest
将其放入测试 HTTP 服务器中。