英文:
golang how to live test an http server?
问题
我使用了gotests和gorilla mux,可以对我的http handlefunc处理程序进行单元测试,但它们没有按照gorilla mux应有的方式响应正确的http请求方法。我该如何进行一个"实时服务器"版本的测试?
func main() {
router := mux.NewRouter()
router.HandleFunc("/", views.Index).Methods("GET")
}
func Index(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "INDEX\n")
}
func TestIndex(t *testing.T) {
req, _ := http.NewRequest("GET", "/", nil)
req1, _ := http.NewRequest("POST", "/", nil)
rr := httptest.NewRecorder()
handler := http.HandlerFunc(Index)
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
args args
}{
{name: "1: testing get", args: args{w: rr, r: req}},
{name: "2: testing post", args: args{w: rr, r: req1}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler.ServeHTTP(tt.args.w, tt.args.r)
log.Println(tt.args.w)
})
}
}
问题在于该函数对GET和POST请求都进行了响应,并没有考虑到我的主路由。这对于单元测试函数来说是可以的,但我认为最好编写一个集成测试,一次性测试整个功能,并将所有东西一次性处理完毕。
英文:
I use gotests, and gorilla mux and I can unit test my http handlefunc handlers, but they do not respond to the proper http request methods as they should under the gorilla mux. How I can do a "live server" version of the test?
func main() {
router := mux.NewRouter()
router.HandleFunc("/", views.Index).Methods("GET")
}
func Index(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "INDEX\n")
}
func TestIndex(t *testing.T) {
req, _ := http.NewRequest("GET", "/", nil)
req1, _ := http.NewRequest("POST", "/", nil)
rr := httptest.NewRecorder()
handler := http.HandlerFunc(Index)
type args struct {
w http.ResponseWriter
r *http.Request
}
tests := []struct {
name string
args args
}{
{name: "1: testing get", args: args{w: rr, r: req}},
{name: "2: testing post", args: args{w: rr, r: req1}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler.ServeHTTP(tt.args.w, tt.args.r)
log.Println(tt.args.w)
})
}
}
The problem here is that the function responds to both the get and post requests and
doens't take into account my main router. This is fine for unit testing the function,
but I think it would be better to just write an integrated test that tests the whole
thing and gets everything out of the way in one go.
答案1
得分: 21
使用net/http/httptest.Server类型来与实际服务器进行测试。
func TestIndex(t *testing.T) {
// 创建一个使用其他地方初始化的路由器的服务器。路由器可以是Gorilla mux,也可以是net/http ServeMux、http.DefaultServeMux或任何满足net/http Handler接口的值。
ts := httptest.NewServer(router)
defer ts.Close()
newreq := func(method, url string, body io.Reader) *http.Request {
r, err := http.NewRequest(method, url, body)
if err != nil {
t.Fatal(err)
}
return r
}
tests := []struct {
name string
r *http.Request
}{
{name: "1: testing get", r: newreq("GET", ts.URL+"/", nil)},
{name: "2: testing post", r: newreq("POST", ts.URL+"/", nil)}, // POST需要提供reader参数
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resp, err := http.DefaultClient.Do(tt.r)
defer resp.Body.Close()
if err != nil {
t.Fatal(err)
}
// 在这里检查预期的响应。
})
}
}
尽管问题中使用了Gorilla mux,但本答案中的方法和细节适用于任何满足http.Handler接口的路由器。
英文:
Use the net/http/httptest.Server type to test with a live server.
func TestIndex(t *testing.T) {
// Create server using the a router initialized elsewhere. The router
// can be a Gorilla mux as in the question, a net/http ServeMux,
// http.DefaultServeMux or any value that statisfies the net/http
// Handler interface.
ts := httptest.NewServer(router)
defer ts.Close()
newreq := func(method, url string, body io.Reader) *http.Request {
r, err := http.NewRequest(method, url, body)
if err != nil {
t.Fatal(err)
}
return r
}
tests := []struct {
name string
r *http.Request
}{
{name: "1: testing get", r: newreq("GET", ts.URL+"/", nil)},
{name: "2: testing post", r: newreq("POST", ts.URL+"/", nil)}, // reader argument required for POST
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resp, err := http.DefaultClient.Do(tt.r)
defer resp.Body.Close()
if err != nil {
t.Fatal(err)
}
// check for expected response here.
})
}
}
Although the question uses Gorilla mux, the approach and details in this answer apply to any router that satisfies the http.Handler interface.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论