如何使用httptesttestinghttp调用
我有以下代码:
package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "time" ) type twitterResult struct { Results []struct { Text string `json:"text"` Ids string `json:"id_str"` Name string `json:"from_user_name"` Username string `json:"from_user"` UserId string `json:"from_user_id_str"` } } var ( twitterUrl = "http://search.twitter.com/search.json?q=%23UCL" pauseDuration = 5 * time.Second ) func retrieveTweets(c chan<- *twitterResult) { for { resp, err := http.Get(twitterUrl) if err != nil { log.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) r := new(twitterResult) //or &twitterResult{} which returns *twitterResult err = json.Unmarshal(body, &r) if err != nil { log.Fatal(err) } c <- r time.Sleep(pauseDuration) } } func displayTweets(c chan *twitterResult) { tweets := <-c for _, v := range tweets.Results { fmt.Printf("%v:%v\n", v.Username, v.Text) } } func main() { c := make(chan *twitterResult) go retrieveTweets(c) for { displayTweets(c) } }
我想写一些testing,但我不知道如何使用httptest包http://golang.org/pkg/net/http/httptest/将欣赏一些指针
我想出了这个(从testing中无耻复制去OAuth https://code.google.com/p/goauth2/source/browse/oauth/oauth_test.go ):
var request = struct { path, query string // request contenttype, body string // response }{ path: "/search.json?", query: "q=%23Kenya", contenttype: "application/json", body: twitterResponse, } var ( twitterResponse = `{ 'results': [{'text':'hello','id_str':'34455w4','from_user_name':'bob','from_user_id_str':'345424'}]}` ) func TestRetrieveTweets(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", request.contenttype) io.WriteString(w, request.body) } server := httptest.NewServer(http.HandlerFunc(handler)) defer server.Close() resp, err := http.Get(server.URL) if err != nil { t.Fatalf("Get: %v", err) } checkBody(t, resp, twitterResponse) } func checkBody(t *testing.T, r *http.Response, body string) { b, err := ioutil.ReadAll(r.Body) if err != nil { t.Error("reading reponse body: %v, want %q", err, body) } if g, w := string(b), body; g != w { t.Errorf("request body mismatch: got %q, want %q", g, w) } }
httptest有两种types的testing:响应和服务器
响应testing:
func TestHeader3D(t *testing.T) { resp := httptest.NewRecorder() uri := "/3D/header/?" path := "/home/test" unlno := "997225821" param := make(url.Values) param["param1"] = []string{path} param["param2"] = []string{unlno} req, err := http.NewRequest("GET", uri+param.Encode(), nil) if err != nil { t.Fatal(err) } http.DefaultServeMux.ServeHTTP(resp, req) if p, err := ioutil.ReadAll(resp.Body); err != nil { t.Fail() } else { if strings.Contains(string(p), "Error") { t.Errorf("header response shouldn't return error: %s", p) } else if !strings.Contains(string(p), `expected result`) { t.Errorf("header response doen't match:\n%s", p) } } }
服务器testing(这是你需要使用的):
func TestIt(t *testing.T){ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprintln(w, `{"fake twitter json string"}`) })) defer ts.Close() twitterUrl = ts.URL c := make(chan *twitterResult) go retrieveTweets(c) tweet := <-c if tweet != expected1 { t.Fail() } tweet = <-c if tweet != expected2 { t.Fail() } }
顺便说一句,你不需要传入r的指针,因为它已经是一个指针了。
err = json.Unmarshal(body, r)
编辑:我的logging器testing,我可以使用我的http处理程序,如下所示:
handler(resp, req)
但我原来的代码是不使用默认的多路复用器(但从大猩猩/多路复用器),我有一些绕过多路复用器,如插入服务器日志logging,并添加请求上下文(大猩猩/上下文),所以我不得不从多路复用调用ServeHTTP
如果你想testing你的程序,通常最好在testing的时候写出来。 例如,如果您将retrieveTweets
函数的内部循环retrieveTweets
为如下所示:
func downloadTweets(tweetsUrl string) (*twitterResult, error)
你可以用你使用httptest
包设置的testing服务器的URL来调用它,而不必担心睡眠或重复的请求。
myserver_test.go
package myserver import ( "fmt" "io/ioutil" "net/http" "net/http/httptest" "testing" ) func TestMyHandler(t *testing.T) { handler := &MyHandler{} server := httptest.NewServer(handler) defer server.Close() for _, i := range []int{1, 2} { resp, err := http.Get(server.URL) if err != nil { t.Fatal(err) } if resp.StatusCode != 200 { t.Fatalf("Received non-200 response: %d\n", resp.StatusCode) } expected := fmt.Sprintf("Visitor count: %d.", i) actual, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatal(err) } if expected != string(actual) { t.Errorf("Expected the message '%s'\n", expected) } } }
myserver.go
package myserver import ( "fmt" "net/http" "sync" ) type MyHandler struct { sync.Mutex count int } func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { var count int h.Lock() h.count++ count = h.count h.Unlock() fmt.Fprintf(w, "Visitor count: %d.", count) }