2017-04-19 3 views
2

Ich schreibe Tests für einen einfachen REST-Service in GoLang. Aber, weil ich julienschmidt/httprouter als Routing-Bibliothek verwende. Ich kämpfe darum, wie man einen Test schreibt.Wie schreibe ich Test mit httprouter

main.go

package main 

func main() { 
    router := httprouter.New() 
    bookController := controllers.NewBookController() 
    router.GET("/book/:id", bookController.GetBook) 
    http.ListenAndServe(":8080", router) 
} 

Controller

package controllers 

type BookController struct {} 

func NewBookController *BookController { 
    return &BookController() 
} 

func (bc BookController) GetBook(w http.ResponseWriter, r *http.Request, p httprouter.Params) { 
    fmt.Fprintf(w,"%s", p) 
} 

Meine Frage ist: Wie kann diese während testen GetBook weder Httphandler noch HttpHandle

Wenn ich einen traditionellen Handler, der Test wird so einfach sein

func TestGetBook(t *testing.T) { 
    req, _ := http.NewRequest("GET", "/book/sampleid", nil) 
    rr := httptest.NewRecorder() 
    handler := controllers.NewBookController().GetBook 
    handler.ServeHTTP(rr,req) 
    if status := rr.code; status != http.StatusOK { 
    t.Errorf("Wrong status") 
    } 
} 

Das Problem ist, httprouter ist nicht Handler oder handlefunc. So bin ich jetzt stecken

+0

Toll ... Ich dachte schon, aber immer am besten zu überprüfen :) – Flimzy

Antwort

3

Nur Spin einen neuen Router für jeden Test und registrieren Sie dann den Handler im Test, dann übergeben Sie die Testanforderung an den Router, nicht der Handler, so dass der Router die Pfadparameter analysieren und übergeben kann sie an den Handler.

func TestGetBook(t *testing.T) { 
    handler := controllers.NewBookController() 
    router := httprouter.New() 
    router.GET("/book/:id", handler.GetBook) 

    req, _ := http.NewRequest("GET", "/book/sampleid", nil) 
    rr := httptest.NewRecorder() 

    router.ServeHTTP(rr, req) 
    if status := rr.code; status != http.StatusOK { 
     t.Errorf("Wrong status") 
    } 
} 
+0

Danke. Das funktioniert für mich. Aber denkst du, dass es einen anderen Weg gibt, den Testcode einfacher zu schreiben? Vielleicht machen Änderungen Paket Haupt? – JSNoob

+0

Hängt davon ab, was Sie in diesem Test für schwer zu schreiben halten ... Wenn Sie viele solche 'TestXxx'-Funktionen zum Testen verschiedener Handler haben und das Gefühl haben, dass Sie sich oft wiederholen, können Sie Repetitive Code in eine Funktion extrahieren und verwende es in deinen Tests. Z.B. Sie könnten eine Funktion haben, nennen wir sie "Testrouter", die einen neuen Router erstellt, jeden Handler registriert und dann den Router zurückgibt, und Sie können die 'rr' und' req' direkt an ihr Ergebnis übergeben wie 'testrouter() .ServeHTTP (rr, req) '... – mkopriva

+1

10 Und wenn Sie einen einzelnen Handler mit vielen verschiedenen Anforderungen testen möchten, sehen Sie sich [table driven tests] an (https://github.com/golang/go/wiki/TableDrivenTests). – mkopriva

0

Sie benötigen Handler wickeln, so dass es als http.HandlerFunc zugegriffen werden kann:

func TestGetBook(t *testing.T) { 
    req, _ := http.NewRequest("GET", "/book/sampleid", nil) 
    rr := httptest.NewRecorder() 
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     controllers.NewBookController().GetBook(w, r, httprouter.Params{}) 
    }) 
    handler.ServeHTTP(rr,req) 
    if status := rr.code; status != http.StatusOK { 
     t.Errorf("Wrong status") 
    } 
} 

Wenn Ihr Handler Parameter erfordert, werden Sie entweder sie von der Anforderung manuell zu analysieren, oder gib sie nur als drittes Argument an.

Verwandte Themen