How to test an endpoint in go?

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

How to test an endpoint in go?

问题

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

这是我的project.go代码:

package main

import (
    "encoding/json"
    "net/http"

    "github.com/gorilla/mux"
    "github.com/rs/cors"
)

type Person struct {
    ID        string   `json:"id,omitempty"`
    Firstname string   `json:"firstname,omitempty"`
    Lastname  string   `json:"lastname,omitempty"`
    Address   *Address `json:"address,omitempty"`
}

type Address struct {
    City  string `json:"city,omitempty"`
    State string `json:"state,omitempty"`
}

var people []Person

func GetPersonEndpoint(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for _, item := range people {
        if item.ID == params["id"] {
            json.NewEncoder(w).Encode(item)
            return
        }
    }
    json.NewEncoder(w).Encode(&Person{})
}

func GetPeopleEndpoint(w http.ResponseWriter, req *http.Request) {
    json.NewEncoder(w).Encode(people)
}

func CreatePersonEndpoint(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    var person Person
    _ = json.NewDecoder(req.Body).Decode(&person)
    person.ID = params["id"]
    people = append(people, person)
    json.NewEncoder(w).Encode(people)
}

func DeletePersonEndpoint(w http.ResponseWriter, req *http.Request) {
    params := mux.Vars(req)
    for index, item := range people {
        if item.ID == params["id"] {
            people = append(people[:index], people[index+1:]...)
            break
        }
    }
    json.NewEncoder(w).Encode(people)
}

func main() {
    Router := mux.NewRouter()
    people = append(people, Person{ID: "1", Firstname: "sarath", Lastname: "v", Address: &Address{City: "sunnyvale", State: "CA"}})
    people = append(people, Person{ID: "2", Firstname: "dead", Lastname: "pool"})

    c := cors.New(cors.Options{
        AllowedOrigins:   []string{"http://localhost:3000"},
        AllowCredentials: true,
    })

    // Insert the middleware
    handler := c.Handler(Router)
    http.ListenAndServe(":12345", handler)
}

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

package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
    "testing"
    "encoding/json"
)

func checkResponseCode(t *testing.T, expected, actual int) {
    if expected != actual {
        t.Errorf("Expected response code %d. Got %d\n", expected, actual)
    }
}

func executeRequest(req *http.Request) *httptest.ResponseRecorder {
    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(GetPersonEndpoint)
    handler.ServeHTTP(rr, req)
    if status := rr.Code; status != http.StatusOK {
        fmt.Printf("Handler returned wrong status code: got %v want %v", status, http.StatusOK)
    }
    return rr
}

func TestGetPersonEndPoint(t *testing.T) {
    req, _ := http.NewRequest("GET", "/people/5", nil)
    response := executeRequest(req)
    checkResponseCode(t, http.StatusNotFound, response.Code)
    var m map[string]string
    json.Unmarshal(response.Body.Bytes(), &m)
    if m["error"] != "Product not found" {
        t.Errorf("Expected the 'error' key of the response to be set to 'Product not found'. Got '%s'", m["error"])
    }
}

最后,这是错误信息:

./new.go:14: main redeclared in this block
previous declaration at ./myproject.go:62
./new.go:20: not enough arguments in call to server.ListenAndServeTLS
have ()
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:

package main
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/cors"
)
type Person struct {
ID        string   `json:"id,omitempty"`
Firstname string   `json:"firstname,omitempty"`
Lastname  string   `json:"lastname,omitempty"`
Address   *Address `json:"address,omitempty"`
}
type Address struct {
City  string `json:"city,omitempty"`
State string `json:"state,omitempty"`
}
var people []Person;
func GetPersonEndpoint(w http.ResponseWriter, req *http.Request) {
params := mux.Vars(req)
for _, item := range people {
if item.ID == params["id"] {
json.NewEncoder(w).Encode(item)
return
}
}
json.NewEncoder(w).Encode(&Person{})
}
func GetPeopleEndpoint(w http.ResponseWriter, req *http.Request) {
json.NewEncoder(w).Encode(people)
}
func CreatePersonEndpoint(w http.ResponseWriter, req *http.Request) {
params := mux.Vars(req)
var person Person
_ = json.NewDecoder(req.Body).Decode(&person)
person.ID = params["id"]
people = append(people, person)
json.NewEncoder(w).Encode(people)
}
func DeletePersonEndpoint(w http.ResponseWriter, req *http.Request) {
params := mux.Vars(req)
for index, item := range people {
if item.ID == params["id"] {
people = append(people[:index], people[index+1:]...)
break
}
}
json.NewEncoder(w).Encode(people)
}
func main() {
Router := mux.NewRouter()
people = append(people, Person{ID: "1", Firstname: "sarath", Lastname: "v", Address: &Address{City: "sunnyvale", State: "CA"}})
people = append(people, Person{ID: "2", Firstname: "dead", Lastname: "pool"})
// router.PathPrefix("/tmpfiles/").Handler(http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("."))))
Router.HandleFunc("/people", GetPeopleEndpoint).Methods("GET")
Router.HandleFunc("/people/{id}", GetPersonEndpoint).Methods("GET")
Router.HandleFunc("/people/{id}", CreatePersonEndpoint).Methods("POST")
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000"},
AllowCredentials: true,
})
// Insert the middleware
handler := c.Handler(Router)
http.ListenAndServe(":12345", handler)
}

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

package main
import (
"."
"net/http"
"net/http/httptest"
"testing"
"encoding/json"
)
func checkResponseCode(t *testing.T, expected, actual int) {
if expected != actual {
t.Errorf("Expected response code %d. Got %d\n", expected, actual)
}
}
func executeRequest(req *http.Request) *httptest.ResponseRecorder {
rr := httptest.NewRecorder()
handler := http.HandlerFunc(GetPersonEndpoint)
handler.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
fmt.Printf("Handler returned wrong status code: got %v want %v" , status, http.statusOk);
}
return rr
}
func TestGetPersonEndPoint(t *testing.T){
req, _ := http.NewRequest("GET", "/people/5", nil)
response := executeRequest(req)
checkResponseCode(t, http.StatusNotFound, response.Code)
var m map[string]string
json.Unmarshal(response.Body.Bytes(), &m)
if m["error"] != "Product not found" {
t.Errorf("Expected the 'error' key of the response to be set to 'Product not found'. Got '%s'", m["error"])
}
}

And finally this is the error:

./new.go:14: main redeclared in this block
previous declaration at ./myproject.go:62
./new.go:20: not enough arguments in call to server.ListenAndServeTLS
have ()
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

    // Arrange
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)

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:

确定