2013-04-22 15 views
47

ho il seguente codice:Come verificare http chiamate in movimento utilizzando httptest

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) 
    } 

} 

mi piacerebbe scrivere alcuni test per esso, ma non sono sicuro di come utilizzare il pacchetto httptest http://golang.org/pkg/net/http/httptest/ sarebbe apprezzare alcune indicazioni

sono arrivato fino a questo (spudoratamente copiato dai test per OAuth Go 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) 
    } 
} 

risposta

5

Se volete testare il vostro programma, è spesso è meglio scrivere con i test in mente. Ad esempio, se è stato estratto il ciclo interno della funzione retrieveTweets in qualcosa di simile a questo:

func downloadTweets(tweetsUrl string) (*twitterResult, error) 

Si potrebbe richiamare con l'URL di un server di prova che hai impostato utilizzando il pacchetto httptest, senza doversi preoccupare di i posti letto o le richieste ripetute.

+0

Posso prendere in giro un server? Penso che bagnare un server di test neghi lo scopo del test, se posso prendere in giro un server e la risposta che mi aspetto si adatti bene al test – jwesonga

+0

Il pacchetto 'httptest' è l'infrastruttura per configurare un piccolo Server HTTP per i test. È possibile implementare i gestori delle richieste nello stesso modo in cui si farebbe normalmente, quindi eseguire il codice su quel server anziché su Twitter. –

64

httptest fa due tipi di test: la risposta e il server

prova di risposta:

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) 
      } 
    } 
} 

prova Server (che è ciò che è necessario utilizzare):

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, è non è necessario passare il puntatore di r, perché è già un puntatore.

err = json.Unmarshal(body, r) 

EDIT: per la mia prova di registratore, ho potuto usare il mio gestore HTTP in questo modo:

handler(resp, req) 

Ma il mio codice originale non utilizza il mux di default (ma da Gorilla/mux), e ho avere qualche involucro attorno al mux, ad es inserire la registrazione del server, e l'aggiunta di contesto di richiesta (Gorilla/contesto), così ho dovuto iniziare da mux e chiamare ServeHTTP

+6

Per favore, aggiungi il codice completo, come l'importazione di tutti i pacchetti. Newbie qui;) Grazie! –

+1

Potresti usare i goimports – 030

3

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) 
} 
Problemi correlati