Description
ctx.Status() does not affect httptest.ResponseRecorder while ctx.JSON() does
How to reproduce
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"net/http/httptest"
"testing"
)
func TestName(t *testing.T) {
recorder := httptest.NewRecorder()
c, _ := gin.CreateTestContext(recorder)
changeResponseCode(c)
fmt.Println(recorder.Code)
}
func changeResponseCode(ctx *gin.Context) {
ctx.Status(http.StatusNoContent)
}
Expectations
Should print 204
Actual result
Prints 200
Environment
- go version: 1.23.2
- gin version (or commit ref): 1.10.0
- operating system: Ubuntu 22.04
Comment From: JimChenWYU
c.Status(204)
do not change the recorder.status
but change responseWriter.status
Comment From: ksw2000
It seems that ctx.Status()
In the function changeResponseCode
changes the Writer
in ctx
but doesn't change the recorder
. That is to say, you can fetch the status code by c.Writer.Status()
func TestName(t *testing.T) {
recorder := httptest.NewRecorder()
c, _ := gin.CreateTestContext(recorder)
changeResponseCode(c)
fmt.Println(c.Writer.Status()) // 204
fmt.Println(recorder.Code) // 200
}
Besides, I found a related unit test in response_writer_test.go
https://github.com/gin-gonic/gin/blob/c8a3adc65703d8958265c07689662e54f037038c/response_writer_test.go#L54-L67
func TestResponseWriterWriteHeader(t *testing.T) {
testWriter := httptest.NewRecorder()
writer := &responseWriter{}
writer.reset(testWriter)
w := ResponseWriter(writer)
w.WriteHeader(http.StatusMultipleChoices)
assert.False(t, w.Written())
assert.Equal(t, http.StatusMultipleChoices, w.Status())
assert.NotEqual(t, http.StatusMultipleChoices, testWriter.Code) // ← WHY ?
w.WriteHeader(-1)
assert.Equal(t, http.StatusMultipleChoices, w.Status())
}
I'm not sure why it was designed so that the original testWriter
does not change along with it.