Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Hanaasagi opened this issue Jul 5, 2021 · 6 comments


Copy link

  • 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.


#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.


Lines 9 to 16 in 9c27053

// CreateTestContext returns a fresh engine and context for testing purposes
func CreateTestContext(w http.ResponseWriter) (c *Context, r *Engine) {
r = New()
c = r.allocateContext()

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


Lines 202 to 205 in 9c27053

func (engine *Engine) allocateContext() *Context {
v := make(Params, 0, engine.maxParams)
return &Context{engine: engine, params: &v}

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.


Lines 462 to 479 in 9c27053

if params != nil && cap(*params) > 0 {
if value.params == nil {
value.params = params
// Expand slice within preallocated capacity
i := len(*value.params)
*value.params = (*value.params)[:i+1]
val := path[:end]
if unescape {
if v, err := url.QueryUnescape(val); err == nil {
val = v
(*value.params)[i] = Param{
Key: n.path[1:],
Value: val,

How to reproduce

package main

import (


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 {


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.


  • 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
Copy link

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


Copy link

Hello, Any thoughts on this?

Copy link

RoCry commented Aug 3, 2021

Hello, Any thoughts on this?

@Hanaasagi We met the same issue and fixed it #2803, please feel free to leave suggestions.

Copy link

@Hanaasagi i have same issue, is there any work around

Copy link

jlaneve commented Jul 19, 2022

Here's a workaround for now:


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

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


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

Copy link

fixed in #2803 and released in v1.8.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

5 participants