为了账号安全,请及时绑定邮箱和手机立即绑定

使用路径变量测试 Chi 路径

使用路径变量测试 Chi 路径

Go
吃鸡游戏 2023-06-05 17:33:59
我在测试我的 go-chi 路线时遇到问题,特别是带有路径变量的路线。运行服务器go run main.go工作正常,对路径变量的路由请求按预期运行。当我对路由运行测试时,我总是收到 HTTP 错误:Unprocessable Entity。注销 发生的情况后articleID,似乎articleCtx无法访问路径变量。不确定这是否意味着我需要articleCtx在测试中使用,但我已经尝试ArticleCtx(http.HandlerFunc(GetArticleID))并得到错误:panic: interface conversion: interface {} is nil, not *chi.Context [recovered]    panic: interface conversion: interface {} is nil, not *chi.Context运行服务器:go run main.go测试服务器:go test .我的来源:// main.gopackage mainimport (    "context"    "fmt"    "net/http"    "strconv"    "github.com/go-chi/chi")type ctxKey struct {    name string}func main() {    r := chi.NewRouter()    r.Route("/articles", func(r chi.Router) {        r.Route("/{articleID}", func(r chi.Router) {            r.Use(ArticleCtx)            r.Get("/", GetArticleID) // GET /articles/123        })    })    http.ListenAndServe(":3333", r)}// ArticleCtx gives the routes using it access to the requested article ID in the pathfunc ArticleCtx(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        articleParam := chi.URLParam(r, "articleID")        articleID, err := strconv.Atoi(articleParam)        if err != nil {            http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)            return        }        ctx := context.WithValue(r.Context(), ctxKey{"articleID"}, articleID)        next.ServeHTTP(w, r.WithContext(ctx))    })}// GetArticleID returns the article ID that the client requestedfunc GetArticleID(w http.ResponseWriter, r *http.Request) {    ctx := r.Context()    articleID, ok := ctx.Value(ctxKey{"articleID"}).(int)    if !ok {        http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)        return    }    w.Write([]byte(fmt.Sprintf("article ID:%d", articleID)))}
查看完整描述

4 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

有一个类似的问题,虽然我直接对处理程序进行单元测试。httptest.NewRequest基本上,当使用强制您手动添加时,url 参数似乎不会自动添加到请求上下文中。


以下内容对我有用。


w := httptest.NewRecorder()

r := httptest.NewRequest("GET", "/{key}", nil)


rctx := chi.NewRouteContext()

rctx.URLParams.Add("key", "value")


r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))


handler := func(w http.ResponseWriter, r *http.Request) {

    value := chi.URLParam(r, "key")

}

handler(w, r)

全部归功于soedar =)



查看完整回答
反对 回复 2023-06-05
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

我对命名路径变量有同样的问题。我能够解决它为我的测试设置路由器。go-chi 测试显示了一个好的样本。

查看完整回答
反对 回复 2023-06-05
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

现在可能迟到了 :) 但也许其他人会发现它有用。


我遇到了同样的问题,并希望将我的测试结构化为一个片段,所以我最终创建了一个“帮助程序”函数,以便向请求添加所需的 chi 上下文:


func AddChiURLParams(r *http.Request, params map[string]string) *http.Request {

    ctx := chi.NewRouteContext()

    for k, v := range params {

        ctx.URLParams.Add(k, v)

    }


    return r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, ctx))

}

同样,正如@Ullauri 所提到的,解决方案的所有功劳都归功于soedar。


但是有了这个函数,你就可以像这样在切片中很好地使用它:


{

    name: "OK_100",

    rec:  httptest.NewRecorder(),

    req: AddChiURLParams(httptest.NewRequest("GET", "/articles/100", nil), map[string]string{

        "id": "100",

    }),

    expectedBody: `article ID:100`,

},

希望这可以帮助!:)


查看完整回答
反对 回复 2023-06-05
?
阿晨1998

TA贡献2037条经验 获得超6个赞

在您指导定义 path 之后main的用法,但在您的测试中您只是直接使用。ArticleCtx/articlesArticleCtx

您的测试请求不应包含/articles,例如:

httptest.NewRequest("GET", "/1", nil)


查看完整回答
反对 回复 2023-06-05
  • 4 回答
  • 0 关注
  • 122 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信