gin icon indicating copy to clipboard operation
gin copied to clipboard

Use the gin.CreateTestContext in test, could not get the param in the route.

Open Hanaasagi opened this issue 2 years ago • 5 comments

  • With issues:
    • Use the search tool before opening a new issue.
    • Please provide source code and commit sha if you found a bug.
    • Review existing issues and provide feedback or react to them.

Description

https://github.com/gin-gonic/gin/pull/2755 only fixes the slice bounds out of range panic. Route params are not be handled correctly in test context. I can explain what happened.

When call CreateTestContext, it will call New function to create a Engine. The maxParams will be the default value 0.

https://github.com/gin-gonic/gin/blob/9c27053243cb24ecc90d01c8ff379bd98fed9c8e/test_helpers.go#L9-L16

Then allocateContext init the Params. The cap and len are both 0. params is the reference of Params.

https://github.com/gin-gonic/gin/blob/9c27053243cb24ecc90d01c8ff379bd98fed9c8e/gin.go#L202-L205

Even if we add a route, it only incrs the maxParams value, it has not effect on the Context we created by CreateTestContext before. The condition will always be false.

https://github.com/gin-gonic/gin/blob/9c27053243cb24ecc90d01c8ff379bd98fed9c8e/tree.go#L462-L479

How to reproduce

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/gin-gonic/gin"
)

func main() {
	w := httptest.NewRecorder()
	ctx, engine := gin.CreateTestContext(w)
	engine.GET("/hello/:name", func(ctx *gin.Context) {
		fmt.Printf("Param name is %s\n", ctx.Param("name"))
		ctx.String(http.StatusOK, "Hello %s", ctx.Param("name"))
	})
	var err error
	ctx.Request, err = http.NewRequest(http.MethodGet, "/hello/world", nil)
	if err != nil {
		panic(err)
	}
	engine.HandleContext(ctx)
}

Expectations

Get following output after running the code.

[GIN-debug] GET    /hello/:name              --> main.main.func1 (1 handlers)
Param name is world

Actual result

[GIN-debug] GET    /hello/:name              --> main.main.func1 (1 handlers)
Param name is 

ctx.Param("name") returns a empty string.

Environment

  • go version: go version go1.16 darwin/amd64
  • gin version (or commit ref): v1.7.2-0.20210704023713-9c27053243cb
  • operating system: macOs Big Sur 11.4, Darwin Kernel Version 20.5.0

Hanaasagi avatar Jul 05 '21 18:07 Hanaasagi

One way to fix this problem is check the cap of params everytime when we use.

图片

Hanaasagi avatar Jul 05 '21 19:07 Hanaasagi

Hello, Any thoughts on this?

Hanaasagi avatar Jul 09 '21 18:07 Hanaasagi

Hello, Any thoughts on this?

@Hanaasagi We met the same issue and fixed it https://github.com/gin-gonic/gin/pull/2803, please feel free to leave suggestions.

RoCry avatar Aug 03 '21 09:08 RoCry

@Hanaasagi i have same issue, is there any work around https://github.com/gin-gonic/gin/issues/2833

alochym01 avatar Aug 20 '21 03:08 alochym01

Here's a workaround for now:

gin.SetMode(gin.TestMode)

w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)

c.Params = []gin.Param{gin.Param{Key: "k", Value: "v"}}

foo(c)

if w.Code != 200 {
    b, _ := ioutil.ReadAll(w.Body)
    t.Error(w.Code, string(b))
}

jlaneve avatar Jul 19 '22 01:07 jlaneve

fixed in #2803 and released in v1.8.2

appleboy avatar Dec 23 '22 16:12 appleboy