How to test an endpoint in go?

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

How to test an endpoint in go?

问题

我在Go中编写了一个小的测试函数。我在向实际的端点发出请求并进行测试方面遇到了困难。我尝试导入具有处理程序函数的文件(我认为我试图导入整个目录:import (".""))。我的project.go和handler_test.go文件都在同一个目录中(我认为这并不重要)。有人可以给我一些提示,这样我就可以编写更多的测试了。

这是我的project.go代码:

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/gorilla/mux"
  6. "github.com/rs/cors"
  7. )
  8. type Person struct {
  9. ID string `json:"id,omitempty"`
  10. Firstname string `json:"firstname,omitempty"`
  11. Lastname string `json:"lastname,omitempty"`
  12. Address *Address `json:"address,omitempty"`
  13. }
  14. type Address struct {
  15. City string `json:"city,omitempty"`
  16. State string `json:"state,omitempty"`
  17. }
  18. var people []Person
  19. func GetPersonEndpoint(w http.ResponseWriter, req *http.Request) {
  20. params := mux.Vars(req)
  21. for _, item := range people {
  22. if item.ID == params["id"] {
  23. json.NewEncoder(w).Encode(item)
  24. return
  25. }
  26. }
  27. json.NewEncoder(w).Encode(&Person{})
  28. }
  29. func GetPeopleEndpoint(w http.ResponseWriter, req *http.Request) {
  30. json.NewEncoder(w).Encode(people)
  31. }
  32. func CreatePersonEndpoint(w http.ResponseWriter, req *http.Request) {
  33. params := mux.Vars(req)
  34. var person Person
  35. _ = json.NewDecoder(req.Body).Decode(&person)
  36. person.ID = params["id"]
  37. people = append(people, person)
  38. json.NewEncoder(w).Encode(people)
  39. }
  40. func DeletePersonEndpoint(w http.ResponseWriter, req *http.Request) {
  41. params := mux.Vars(req)
  42. for index, item := range people {
  43. if item.ID == params["id"] {
  44. people = append(people[:index], people[index+1:]...)
  45. break
  46. }
  47. }
  48. json.NewEncoder(w).Encode(people)
  49. }
  50. func main() {
  51. Router := mux.NewRouter()
  52. people = append(people, Person{ID: "1", Firstname: "sarath", Lastname: "v", Address: &Address{City: "sunnyvale", State: "CA"}})
  53. people = append(people, Person{ID: "2", Firstname: "dead", Lastname: "pool"})
  54. c := cors.New(cors.Options{
  55. AllowedOrigins: []string{"http://localhost:3000"},
  56. AllowCredentials: true,
  57. })
  58. // Insert the middleware
  59. handler := c.Handler(Router)
  60. http.ListenAndServe(":12345", handler)
  61. }

这是我的handler_test.go代码。在这段代码中,我正在测试GetPersonEndPoint。

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/http/httptest"
  6. "testing"
  7. "encoding/json"
  8. )
  9. func checkResponseCode(t *testing.T, expected, actual int) {
  10. if expected != actual {
  11. t.Errorf("Expected response code %d. Got %d\n", expected, actual)
  12. }
  13. }
  14. func executeRequest(req *http.Request) *httptest.ResponseRecorder {
  15. rr := httptest.NewRecorder()
  16. handler := http.HandlerFunc(GetPersonEndpoint)
  17. handler.ServeHTTP(rr, req)
  18. if status := rr.Code; status != http.StatusOK {
  19. fmt.Printf("Handler returned wrong status code: got %v want %v", status, http.StatusOK)
  20. }
  21. return rr
  22. }
  23. func TestGetPersonEndPoint(t *testing.T) {
  24. req, _ := http.NewRequest("GET", "/people/5", nil)
  25. response := executeRequest(req)
  26. checkResponseCode(t, http.StatusNotFound, response.Code)
  27. var m map[string]string
  28. json.Unmarshal(response.Body.Bytes(), &m)
  29. if m["error"] != "Product not found" {
  30. t.Errorf("Expected the 'error' key of the response to be set to 'Product not found'. Got '%s'", m["error"])
  31. }
  32. }

最后,这是错误信息:

  1. ./new.go:14: main redeclared in this block
  2. previous declaration at ./myproject.go:62
  3. ./new.go:20: not enough arguments in call to server.ListenAndServeTLS
  4. have ()
  5. want (string, string)
英文:

I wrote a small test function in go. I'm having hard time in making a request to actual endpoint and test it. I tried importing the file which has the handler function (I think I'm trying to import whole directory : import (".")). Both my project.go and handler_test.go are in the same directory (I don't think this matters). Could someone give me heads up so that I can write more tests.
Here is my project.go:

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/gorilla/mux"
  6. "github.com/rs/cors"
  7. )
  8. type Person struct {
  9. ID string `json:"id,omitempty"`
  10. Firstname string `json:"firstname,omitempty"`
  11. Lastname string `json:"lastname,omitempty"`
  12. Address *Address `json:"address,omitempty"`
  13. }
  14. type Address struct {
  15. City string `json:"city,omitempty"`
  16. State string `json:"state,omitempty"`
  17. }
  18. var people []Person;
  19. func GetPersonEndpoint(w http.ResponseWriter, req *http.Request) {
  20. params := mux.Vars(req)
  21. for _, item := range people {
  22. if item.ID == params["id"] {
  23. json.NewEncoder(w).Encode(item)
  24. return
  25. }
  26. }
  27. json.NewEncoder(w).Encode(&Person{})
  28. }
  29. func GetPeopleEndpoint(w http.ResponseWriter, req *http.Request) {
  30. json.NewEncoder(w).Encode(people)
  31. }
  32. func CreatePersonEndpoint(w http.ResponseWriter, req *http.Request) {
  33. params := mux.Vars(req)
  34. var person Person
  35. _ = json.NewDecoder(req.Body).Decode(&person)
  36. person.ID = params["id"]
  37. people = append(people, person)
  38. json.NewEncoder(w).Encode(people)
  39. }
  40. func DeletePersonEndpoint(w http.ResponseWriter, req *http.Request) {
  41. params := mux.Vars(req)
  42. for index, item := range people {
  43. if item.ID == params["id"] {
  44. people = append(people[:index], people[index+1:]...)
  45. break
  46. }
  47. }
  48. json.NewEncoder(w).Encode(people)
  49. }
  50. func main() {
  51. Router := mux.NewRouter()
  52. people = append(people, Person{ID: "1", Firstname: "sarath", Lastname: "v", Address: &Address{City: "sunnyvale", State: "CA"}})
  53. people = append(people, Person{ID: "2", Firstname: "dead", Lastname: "pool"})
  54. // router.PathPrefix("/tmpfiles/").Handler(http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("."))))
  55. Router.HandleFunc("/people", GetPeopleEndpoint).Methods("GET")
  56. Router.HandleFunc("/people/{id}", GetPersonEndpoint).Methods("GET")
  57. Router.HandleFunc("/people/{id}", CreatePersonEndpoint).Methods("POST")
  58. c := cors.New(cors.Options{
  59. AllowedOrigins: []string{"http://localhost:3000"},
  60. AllowCredentials: true,
  61. })
  62. // Insert the middleware
  63. handler := c.Handler(Router)
  64. http.ListenAndServe(":12345", handler)
  65. }

Here is my handler_test.go. In this code I'm testing GetPersonEndPoint.

  1. package main
  2. import (
  3. "."
  4. "net/http"
  5. "net/http/httptest"
  6. "testing"
  7. "encoding/json"
  8. )
  9. func checkResponseCode(t *testing.T, expected, actual int) {
  10. if expected != actual {
  11. t.Errorf("Expected response code %d. Got %d\n", expected, actual)
  12. }
  13. }
  14. func executeRequest(req *http.Request) *httptest.ResponseRecorder {
  15. rr := httptest.NewRecorder()
  16. handler := http.HandlerFunc(GetPersonEndpoint)
  17. handler.ServeHTTP(rr, req)
  18. if status := rr.Code; status != http.StatusOK {
  19. fmt.Printf("Handler returned wrong status code: got %v want %v" , status, http.statusOk);
  20. }
  21. return rr
  22. }
  23. func TestGetPersonEndPoint(t *testing.T){
  24. req, _ := http.NewRequest("GET", "/people/5", nil)
  25. response := executeRequest(req)
  26. checkResponseCode(t, http.StatusNotFound, response.Code)
  27. var m map[string]string
  28. json.Unmarshal(response.Body.Bytes(), &m)
  29. if m["error"] != "Product not found" {
  30. t.Errorf("Expected the 'error' key of the response to be set to 'Product not found'. Got '%s'", m["error"])
  31. }
  32. }

And finally this is the error:

  1. ./new.go:14: main redeclared in this block
  2. previous declaration at ./myproject.go:62
  3. ./new.go:20: not enough arguments in call to server.ListenAndServeTLS
  4. have ()
  5. want (string, string)

答案1

得分: 3

请看一下我写的一些HTTP测试:https://github.com/eamonnmcevoy/go_web_server/blob/master/pkg/server/user_router_test.go

// 准备
us := mock.UserService{}
testUserRouter := NewUserRouter(&us, mux.NewRouter())
...
w := httptest.NewRecorder()
r, _ := http.NewRequest("PUT", "/", payload)
r.Header.Set("Content-Type", "application/json")
testUserRouter.ServeHTTP(w, r)

只需创建一个路由器实例,并使用Go的httptest调用端点。这段代码将在默认端点/执行一个PUT请求。

英文:

Have a look at some http tests I've written: https://github.com/eamonnmcevoy/go_web_server/blob/master/pkg/server/user_router_test.go

  1. // Arrange
  2. us := mock.UserService{}
  3. testUserRouter := NewUserRouter(&us, mux.NewRouter())
  4. ...
  5. w := httptest.NewRecorder()
  6. r, _ := http.NewRequest("PUT", "/", payload)
  7. r.Header.Set("Content-Type", "application/json")
  8. testUserRouter.ServeHTTP(w, r)

Simply create an instance of your router and call the endpoints using go's httptest. This snippet will perform a PUT request at the default endpoint /

huangapple
  • 本文由 发表于 2017年6月27日 04:49:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/44768451.html
匿名

发表评论

匿名网友

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

确定