英文:
Why does gin SetCookie add new cookies but not change the old ones?
问题
我正在尝试测试 Logout 处理程序,其中有一个 ctx.SetCookie
方法:
func (a *authController) Logout(ctx *gin.Context) {
refreshToken, err := ctx.Cookie("refresh_token")
...
ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}
测试函数中的代码:
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.SetCookie("logged_in", "truee", 60*60, "/", "localhost", false, false)
req, _ := http.NewRequest("GET", "/logout", nil)
http.SetCookie(recorder, &http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true}})
http.SetCookie(recorder, &http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
req.Header = http.Header{"Cookie": recorder.Result().Header["Set-Cookie"]}
ctx.Request = req
test.mock()
authController.Logout(ctx)
调用后,我尝试检查 cookie 是否已被删除:
cookies := recorder.Result().Cookies()
for _, c := range cookies {
if c.Name == "access_token" {
assert.Equal(t, "", c.Value)
}
...
}
我遇到的问题是 SetCookie
方法不会更改 cookie,而是添加新的 cookie。也就是说,在调用该方法后,我有两对带有 access Token 的 cookie。
结果导致测试未通过。我不明白我做错了什么,是否可以解决?或者这是正常的行为?
英文:
I'm trying to test the Logout handler where there is a ctx.SetCookie
method:
func (a *authController) Logout(ctx *gin.Context) {
refreshToken, err := ctx.Cookie("refresh_token")
...
ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}
code inside the test function:
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.SetCookie("logged_in", "truee", 60*60, "/", "localhost", false, false)
req, _ := http.NewRequest("GET", "/logout", nil)
http.SetCookie(recorder, &http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true}})
http.SetCookie(recorder, &http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
req.Header = http.Header{"Cookie": recorder.Result().Header["Set-Cookie"]}
ctx.Request = req
test.mock()
authController.Logout(ctx)
After the call, I'm trying to check if the cookies have been deleted:
coockies := recorder.Result().Cookies()
for _, c := range coockies {
if c.Name == "access_token" {
assert.Equal(t, "", c.Value)
}
...
}
And I face such a problem that setCookie does not change cookies , but adds new ones . That is, after calling this method, I have two pairs of cookies with access Token, etc.
And as a result, the tests do not pass. I don't understand I'm doing something wrong and can it be solved somehow? or is that how it should be ?
答案1
得分: 1
使用AddCookie
为recorder
设置cookie。
我认为你应该像这样测试Logout
处理程序:
package ${your_package}
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func Logout(ctx *gin.Context) {
// refreshToken, err := ctx.Cookie("refresh_token")
ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}
func setupRouter() *gin.Engine {
r := gin.Default()
r.GET("/logout", Logout)
return r
}
func TestLogout(t *testing.T) {
w := httptest.NewRecorder()
r := setupRouter()
req, err := http.NewRequest("GET", "/logout", nil)
assert.Nil(t, err)
req.AddCookie(&http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
req.AddCookie(&http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
r.ServeHTTP(w, req)
for _, v := range w.Result().Cookies() {
if v.Name == "access_token" {
assert.Equal(t, "", v.Value)
}
}
assert.Equal(t, http.StatusOK, w.Code)
respBody := &gin.H{}
err = json.Unmarshal(w.Body.Bytes(), respBody)
assert.Nil(t, err)
assert.Equal(t, gin.H{"status": "success"}, *respBody)
}
=== RUN TestLogout
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /logout --> app.Logout (3 handlers)
[GIN] 2022/09/19 - 10:46:00 | 200 | 81μs | | GET "/logout"
--- PASS: TestLogout (0.00s)
PASS
参考:https://gin-gonic.com/docs/testing/
英文:
Use AddCookie
to set cookie for the recorder
.
I think you should test the Logout
handler like this:
package ${your_package}
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func Logout(ctx *gin.Context) {
// refreshToken, err := ctx.Cookie("refresh_token")
ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}
func setupRouter() *gin.Engine {
r := gin.Default()
r.GET("/logout", Logout)
return r
}
func TestLogout(t *testing.T) {
w := httptest.NewRecorder()
r := setupRouter()
req, err := http.NewRequest("GET", "/logout", nil)
assert.Nil(t, err)
req.AddCookie(&http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
req.AddCookie(&http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
r.ServeHTTP(w, req)
for _, v := range w.Result().Cookies() {
if v.Name == "access_token" {
assert.Equal(t, "", v.Value)
}
}
assert.Equal(t, http.StatusOK, w.Code)
respBody := &gin.H{}
err = json.Unmarshal(w.Body.Bytes(), respBody)
assert.Nil(t, err)
assert.Equal(t, gin.H{"status": "success"}, *respBody)
}
=== RUN TestLogout
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /logout --> app.Logout (3 handlers)
[GIN] 2022/09/19 - 10:46:00 | 200 | 81µs | | GET "/logout"
--- PASS: TestLogout (0.00s)
PASS
Reference: https://gin-gonic.com/docs/testing/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论