Gin reverse proxy tests failing for interface conversion: *httptest.ResponseRecorder is not http.CloseNotifier: missing method CloseNotify

Viewed 266

I build a Go Gin reverse proxy API using this page as a guideline: https://le-gall.bzh/author/sebastien-le-gall/

When I try to run tests, I get an error: interface conversion: *httptest.ResponseRecorder is not http.CloseNotifier: missing method CloseNotify C:/Program Files/Go/src/runtime/iface.go:91 (0x1ab53b)

My test looks something like this:

func Test(t *testing.T) {
    expect(t).
        GET("/my/path/"). // make a request to the configured router
        Expect().                           // expect the response
        Status(http.StatusOK)               // to return with a 200
}

The setup for my tests looks something like this:

var (
    router *gin.Engine
)

func expect(t *testing.T) *httpexpect.Expect {
    // Create httpexpect instance
    e := httpexpect.WithConfig(httpexpect.Config{
        Client: &http.Client{
            // ensure requests are made against our app router
            Transport: httpexpect.NewBinder(router),
            Jar:       httpexpect.NewJar(),
        },
        Reporter: httpexpect.NewAssertReporter(t),
        Printers: []httpexpect.Printer{
            httpexpect.NewDebugPrinter(t, true),
        },
    })
    return e
}

This setup worked fine before I converted it from a standard API into a reverse proxy. I'm not sure what to change to fix this error.

1 Answers

@DavidYappeter solution works:

instead of

rr := httptest.NewRecorder()
// creates a test context and gin engine
_, r := gin.CreateTestContext(rr)

we can copy wraper methods mentioned in

https://github.com/gin-gonic/gin/blob/ce20f107f5dc498ec7489d7739541a25dcd48463/context_test.go#L1747-L1765

so now testing will be

func TestProxyHandler(t *testing.T) {
        expected := "dummy data"
        server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, expected)
        }))
        defer server.Close()
        rr := CreateTestResponseRecorder()
        // creates a test context and gin engine
        _, r := gin.CreateTestContext(rr)
   
    
        r.GET("/test", ProxyHandler)
    
        request, _ := http.NewRequest(http.MethodGet, "/test", http.NoBody)
        r.ServeHTTP(rr, request)
        assert.Equal(t, http.StatusOK, rr.Code)
    
    }

type TestResponseRecorder struct {
    *httptest.ResponseRecorder
    closeChannel chan bool
}

func (r *TestResponseRecorder) CloseNotify() <-chan bool {
    return r.closeChannel
}

func (r *TestResponseRecorder) closeClient() {
    r.closeChannel <- true
}

func CreateTestResponseRecorder() *TestResponseRecorder {
    return &TestResponseRecorder{
        httptest.NewRecorder(),
        make(chan bool, 1),
    }
}
Related