如何在Golang中进行HTTP服务器的实时测试?

huangapple go评论112阅读模式
英文:

golang how to live test an http server?

问题

我使用了gotests和gorilla mux,可以对我的http handlefunc处理程序进行单元测试,但它们没有按照gorilla mux应有的方式响应正确的http请求方法。我该如何进行一个"实时服务器"版本的测试?

  1. func main() {
  2. router := mux.NewRouter()
  3. router.HandleFunc("/", views.Index).Methods("GET")
  4. }
  5. func Index(w http.ResponseWriter, r *http.Request) {
  6. w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  7. w.WriteHeader(http.StatusOK)
  8. fmt.Fprintf(w, "INDEX\n")
  9. }
  10. func TestIndex(t *testing.T) {
  11. req, _ := http.NewRequest("GET", "/", nil)
  12. req1, _ := http.NewRequest("POST", "/", nil)
  13. rr := httptest.NewRecorder()
  14. handler := http.HandlerFunc(Index)
  15. type args struct {
  16. w http.ResponseWriter
  17. r *http.Request
  18. }
  19. tests := []struct {
  20. name string
  21. args args
  22. }{
  23. {name: "1: testing get", args: args{w: rr, r: req}},
  24. {name: "2: testing post", args: args{w: rr, r: req1}},
  25. }
  26. for _, tt := range tests {
  27. t.Run(tt.name, func(t *testing.T) {
  28. handler.ServeHTTP(tt.args.w, tt.args.r)
  29. log.Println(tt.args.w)
  30. })
  31. }
  32. }

问题在于该函数对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?

  1. func main() {
  2. router := mux.NewRouter()
  3. router.HandleFunc("/", views.Index).Methods("GET")
  4. }
  5. func Index(w http.ResponseWriter, r *http.Request) {
  6. w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  7. w.WriteHeader(http.StatusOK)
  8. fmt.Fprintf(w, "INDEX\n")
  9. }
  10. func TestIndex(t *testing.T) {
  11. req, _ := http.NewRequest("GET", "/", nil)
  12. req1, _ := http.NewRequest("POST", "/", nil)
  13. rr := httptest.NewRecorder()
  14. handler := http.HandlerFunc(Index)
  15. type args struct {
  16. w http.ResponseWriter
  17. r *http.Request
  18. }
  19. tests := []struct {
  20. name string
  21. args args
  22. }{
  23. {name: "1: testing get", args: args{w: rr, r: req}},
  24. {name: "2: testing post", args: args{w: rr, r: req1}},
  25. }
  26. for _, tt := range tests {
  27. t.Run(tt.name, func(t *testing.T) {
  28. handler.ServeHTTP(tt.args.w, tt.args.r)
  29. log.Println(tt.args.w)
  30. })
  31. }
  32. }

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类型来与实际服务器进行测试。

  1. func TestIndex(t *testing.T) {
  2. // 创建一个使用其他地方初始化的路由器的服务器。路由器可以是Gorilla mux,也可以是net/http ServeMux、http.DefaultServeMux或任何满足net/http Handler接口的值。
  3. ts := httptest.NewServer(router)
  4. defer ts.Close()
  5. newreq := func(method, url string, body io.Reader) *http.Request {
  6. r, err := http.NewRequest(method, url, body)
  7. if err != nil {
  8. t.Fatal(err)
  9. }
  10. return r
  11. }
  12. tests := []struct {
  13. name string
  14. r *http.Request
  15. }{
  16. {name: "1: testing get", r: newreq("GET", ts.URL+"/", nil)},
  17. {name: "2: testing post", r: newreq("POST", ts.URL+"/", nil)}, // POST需要提供reader参数
  18. }
  19. for _, tt := range tests {
  20. t.Run(tt.name, func(t *testing.T) {
  21. resp, err := http.DefaultClient.Do(tt.r)
  22. defer resp.Body.Close()
  23. if err != nil {
  24. t.Fatal(err)
  25. }
  26. // 在这里检查预期的响应。
  27. })
  28. }
  29. }

尽管问题中使用了Gorilla mux,但本答案中的方法和细节适用于任何满足http.Handler接口的路由器。

英文:

Use the net/http/httptest.Server type to test with a live server.

  1. func TestIndex(t *testing.T) {
  2. // Create server using the a router initialized elsewhere. The router
  3. // can be a Gorilla mux as in the question, a net/http ServeMux,
  4. // http.DefaultServeMux or any value that statisfies the net/http
  5. // Handler interface.
  6. ts := httptest.NewServer(router)
  7. defer ts.Close()
  8. newreq := func(method, url string, body io.Reader) *http.Request {
  9. r, err := http.NewRequest(method, url, body)
  10. if err != nil {
  11. t.Fatal(err)
  12. }
  13. return r
  14. }
  15. tests := []struct {
  16. name string
  17. r *http.Request
  18. }{
  19. {name: "1: testing get", r: newreq("GET", ts.URL+"/", nil)},
  20. {name: "2: testing post", r: newreq("POST", ts.URL+"/", nil)}, // reader argument required for POST
  21. }
  22. for _, tt := range tests {
  23. t.Run(tt.name, func(t *testing.T) {
  24. resp, err := http.DefaultClient.Do(tt.r)
  25. defer resp.Body.Close()
  26. if err != nil {
  27. t.Fatal(err)
  28. }
  29. // check for expected response here.
  30. })
  31. }
  32. }

Although the question uses Gorilla mux, the approach and details in this answer apply to any router that satisfies the http.Handler interface.

huangapple
  • 本文由 发表于 2017年2月27日 05:05:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/42474259.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定