使用路径变量测试 Chi 路径

我在测试我的 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.go


package main


import (

    "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 path

func 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 requested

func 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)))

}


吃鸡游戏
浏览 125回答 4
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 =)

拉风的咖菲猫

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

慕哥6287543

现在可能迟到了 :) 但也许其他人会发现它有用。我遇到了同样的问题,并希望将我的测试结构化为一个片段,所以我最终创建了一个“帮助程序”函数,以便向请求添加所需的 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`,},希望这可以帮助!:)

阿晨1998

在您指导定义 path 之后main的用法,但在您的测试中您只是直接使用。ArticleCtx/articlesArticleCtx您的测试请求不应包含/articles,例如:httptest.NewRequest("GET", "/1", nil)
打开App,查看更多内容
随时随地看视频慕课网APP