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.