如何在Golang测试用例中正确Mock http.request并获取gorilla/mux路径参数?
解决测试用例中获取gorilla/mux路径参数的问题
你遇到的核心问题是:gorilla/mux的mux.Vars(req)是从请求的上下文里提取已经完成路由匹配的路径参数,而你直接用http.NewRequest创建的请求,并没有经过mux路由的匹配流程,所以请求上下文里根本没有这些参数,自然拿不到。
下面给你两种实用的解决办法:
方法一:用你的mux路由匹配请求(推荐)
这个方法最贴近真实场景,就是让测试里的请求走一遍mux的路由匹配流程,让路由自动把参数注入到请求上下文里。
修改你的测试代码里的createSearchRequest函数,加入路由匹配的步骤:
func createSearchRequest(rawUrl string) SearchRequest { api := NewWebService() // 注意:你的路由定义的是GET方法,之前代码里写的POST要改成GET,否则路由匹配失败 req, err := http.NewRequest("GET", rawUrl, nil) if err != nil { logger.Fatal(err) } // 关键:用你的实际路由来匹配这个请求,参数会自动注入到请求上下文 router := mux.NewRouter() // 这里要和你实际的路由定义完全一致 router.HandleFunc("/search/{query_type}", api.Search).Methods("GET") // 执行匹配,忽略错误(测试场景下如果路径正确,不会有错误) _ = router.Match(req, nil) logger.Infof("%v", req) return api.searchRequest(req) }
另外注意:你的rawUrl要改成符合路由路径的格式,比如http://localhost/search/content,而不是带?query=test的格式——因为query_type是路径参数,不是URL查询参数。
方法二:手动注入参数到请求上下文
如果你的测试场景很简单,不需要完整的路由匹配,可以直接手动把参数放到请求的上下文里:
func createSearchRequest(rawUrl string) SearchRequest { api := NewWebService() req, err := http.NewRequest("GET", rawUrl, nil) if err != nil { logger.Fatal(err) } // 手动构建路径参数map,注入到请求上下文 vars := map[string]string{"query_type": "content"} // mux用ContextKey(0)作为上下文里存储参数的key req = req.WithContext(context.WithValue(req.Context(), mux.ContextKey(0), vars)) logger.Infof("%v", req) return api.searchRequest(req) }
这个方法更轻量,但缺点是和mux的内部实现耦合,要是mux后续改了上下文key的定义,测试就会失效,所以优先推荐第一种方法。
内容的提问来源于stack exchange,提问作者howie
相关产品推荐
相关产品推荐

