Tak*_*rio 2 reverse-proxy go martini
我正在为马丁尼应用程序编写测试代码,在go中作为反向代理工作,并希望使用它进行测试httptest.ResponseRecorder,但是我得到了以下错误.
[martini] PANIC: interface conversion: *httptest.ResponseRecorder is not http.CloseNotifier: missing method CloseNotify
Run Code Online (Sandbox Code Playgroud)
httptest.ResponseRecorder 没办法 CloseNotify()
我该怎么测试呢?
package main
import (
"github.com/go-martini/martini"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"testing"
)
func TestReverseProxy(t *testing.T) {
// Mock backend
backendResponse := "I am the backend"
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(backendResponse))
}))
defer backend.Close()
backendURL, _ := url.Parse(backend.URL)
// Frontend
m := martini.Classic()
m.Get("/", func(w http.ResponseWriter, r *http.Request) {
proxy := httputil.NewSingleHostReverseProxy(backendURL)
proxy.ServeHTTP(w, r)
})
// Testing
req, _ := http.NewRequest("GET", "/", nil)
res := httptest.NewRecorder()
m.ServeHTTP(res, req)
assert.Equal(t, 200, res.Code, "should be equal")
}
Run Code Online (Sandbox Code Playgroud)
首先,请注意不再按照自述文件中的说明维护马提尼框架.
然后,关于你的问题,这是因为Martini做了一件对我来说非常糟糕的事情:它需要一个http.ResponseWriter并假设它也是一个http.CloseNotifier,而绝对不能保证这一点.他们应该采用自定义界面包装它们,如下所示:
type ResponseWriterCloseNotifier interface {
http.ResponseWriter
http.CloseNotifier
}
Run Code Online (Sandbox Code Playgroud)
你可以在他们的源代码中看到他们对自己的测试有相同的问题,并使用了一些解决方法:https://github.com/go-martini/martini/commit/063dfcd8b0f64f4e2c97f0bc27fa422969baa23b#L13
这是一些用它制作的工作代码:
package main
import (
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"testing"
"github.com/go-martini/martini"
"github.com/stretchr/testify/assert"
)
type closeNotifyingRecorder struct {
*httptest.ResponseRecorder
closed chan bool
}
func newCloseNotifyingRecorder() *closeNotifyingRecorder {
return &closeNotifyingRecorder{
httptest.NewRecorder(),
make(chan bool, 1),
}
}
func (c *closeNotifyingRecorder) close() {
c.closed <- true
}
func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
return c.closed
}
func TestReverseProxy(t *testing.T) {
// Mock backend
backendResponse := "I am the backend"
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(backendResponse))
}))
defer backend.Close()
backendURL, _ := url.Parse(backend.URL)
// Frontend
m := martini.Classic()
m.Get("/", func(w http.ResponseWriter, r *http.Request) {
proxy := httputil.NewSingleHostReverseProxy(backendURL)
proxy.ServeHTTP(w, r)
})
// Testing
req, _ := http.NewRequest("GET", "/", nil)
res := newCloseNotifyingRecorder()
m.ServeHTTP(res, req)
assert.Equal(t, 200, res.Code, "should be equal")
}
Run Code Online (Sandbox Code Playgroud)