J'ai le code suivant:
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)
}
}
Je voudrais écrire quelques tests pour cela, mais je ne sais pas comment utiliser le paquet httptest http://golang.org/pkg/net/http/httptest/ apprécierait certains pointeurs
Je suis venu avec cela (copié sans vergogne à partir des tests pour go 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 fait deux types de tests: réponse et serveur
Test de réponse:
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)
}
}
}
Test du serveur (c'est ce que vous devez utiliser):
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()
}
}
BTW, vous n'avez pas besoin de passer le pointeur de r, car c'est déjà un pointeur.
err = json.Unmarshal(body, r)
EDIT: pour mon test d'enregistreur, je pourrais utiliser mon gestionnaire http comme ceci:
handler(resp, req)
Mais mon code d'origine n'utilise pas le multiplexeur par défaut (mais de Gorilla/mux), et j'ai un peu d'habillage autour du multiplexeur, par exemple insérer la journalisation du serveur et ajouter le contexte de la demande (Gorilla/context), j'ai donc dû commencer à partir du multiplexeur et appeler ServeHTTP
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) } } }
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) }
Si vous souhaitez tester votre programme, il est souvent préférable de l'écrire en gardant à l'esprit les tests. Par exemple, si vous avez extrait la boucle interne de votre fonction retrieveTweets
dans quelque chose comme ceci:
func downloadTweets(tweetsUrl string) (*twitterResult, error)
Vous pouvez l'invoquer avec l'URL d'un serveur de test que vous avez configuré à l'aide du package httptest
sans avoir à vous soucier des mises en veille ou des demandes répétées.