gin
gin copied to clipboard
Unit testing redirect results in panic
Description
When unit testing a HTTP redirect, the result will always be a panic.
How to reproduce
package main
import (
"github.com/gin-gonic/gin"
)
func Something(c *gin.Context) {
c.Redirect(http.StatusFound, "google.com")
}
package main_test
import (
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestSomething(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
Something(c)
assert.Equal(t, http.StatusFound, w.Code)
}
Expectations
I'm expecting the redirect not to panic.
Actual result
testing.tRunner.func1.2({0x1058c73e0, 0x105e3d500}) /usr/local/go/src/testing/testing.go:1526 +0x1c8 testing.tRunner.func1() /usr/local/go/src/testing/testing.go:1529 +0x384 panic({0x1058c73e0, 0x105e3d500}) /usr/local/go/src/runtime/panic.go:884 +0x204 net/http.Redirect({0x12d754dc8?, 0x14000646300}, 0x0, {0x1056d411c, 0xa}, 0x1056a74d0?) /usr/local/go/src/net/http/server.go:2190 +0x60 github.com/gin-gonic/gin/render.Redirect.Render({0x140000c6e88?, 0x0?, {0x1056d411c?, 0x1059576a0?}}, {0x12d754dc8?, 0x14000646300?}) go/pkg/mod/github.com/gin-gonic/[email protected]/render/redirect.go:24 +0x68 github.com/gin-gonic/gin.(*Context).Render(0x14000646300, 0xffffffffffffffff, {0x105992950, 0x140003e7640}) go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:926 +0xf4 github.com/gin-gonic/gin.(*Context).Redirect(...) go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:1014 src/auth.Something(...) src/auth/auth.go:21 src/auth_test.TestSomething(0x0?) src/auth/auth_test.go:24 +0x100
Environment
- go version: go1.21.4 darwin/arm64 (also tested with go1.20.5 darwin/arm64)
- gin version (or commit ref): v1.9.1
- operating system: MacOS Sanoma with Apple Silicon
Created a minimal repo here: https://github.com/Danoctum/gin-redirect-panic
I was able to reproduce it in my environment.
if userId == nil {
c.Redirect(http.StatusTemporaryRedirect, "/login")
}
For it to work, it was necessary to use net/http to redirect.
if userId == nil {
// c.Redirect(http.StatusTemporaryRedirect, "/login")
http.Redirect(c.Writer, c.Request, "/login", http.StatusTemporaryRedirect)
}
Hi @Danoctum and @vinhais
The Nil panic happens as the gin context Request field is nil, you can simply fix it like this
package testgin
import (
"net/http"
"github.com/gin-gonic/gin"
)
func Something(c *gin.Context) {
c.Redirect(http.StatusFound, "google.com")
}
package testgin_test
import (
testgin "gingonic"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func TestSomething(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request, _ = http.NewRequest(http.MethodGet, "/something", nil)
testgin.Something(c)
assert.Equal(t, http.StatusFound, w.Code)
}
Note: Please check out gin documentation https://gin-gonic.com/docs/testing for the proper way of testing gin application.