2016-07-12 62 views
5

Sto lavorando su una API Go che si traduce tra un backend interno e diverse API di terze parti. Sto cercando di capire come testare la sua funzionalità senza effettivamente raggiungere un'API esterna.Test Go (Golang) API richieste in uscita senza effettivamente colpire API di terze parti

Per esempio, ecco un server che gestisce le richieste in entrata per fare nuove canzoni, e invia la richiesta di una terza API parti:

package main 

import (
     "bytes" 
     "encoding/json" 
     "fmt" 
     "net/http" 
) 

var ThirdPartyApi = "http://www.coolsongssite.api" 

type IncomingRequest struct { 
     username string   `json:"username"` 
     password string   `json:"password"` 
     songs []IncomingSong `json:"songs"` 
} 

type OutgoingRequest struct { 
     username string   `json:"username"` 
     password string   `json:"password"` 
     songs []OutgoingSong `json:"songs"` 
} 

type IncomingSong struct { 
     artist string `json:"artist"` 
     album string `json:"album"` 
     title string `json:"title"` 
} 

type OutgoingSong struct { 
     musician string `json:"musician"` 
     record string `json:"record"` 
     name  string `json:"name"` 
} 

func main() { 
     http.HandleFunc("/songs/create", createSong) 
     http.ListenAndServe(":8080", nil) 
} 

func createSong(rw http.ResponseWriter, req *http.Request) { 
     decoder := json.NewDecoder(req.Body) 
     var incomingRequest IncomingRequest 
     decoder.Decode(&incomingRequest) 
     outgoingRequest := incomingRequestToOutgoingRequest(incomingRequest) 

     r, _ := json.Marshal(outgoingRequest) 
     request, _ := http.NewRequest("POST", ThirdPartyApi, bytes.NewBuffer(r)) 
     request.Header.Set("Content-Type", "application/json") 

     client := http.Client{} 

     response, _ := client.Do(request) 
     fmt.Fprintln(rw, response) 
} 

func incomingRequestToOutgoingRequest(inc IncomingRequest) OutgoingRequest { 
     outgoingRequest := OutgoingRequest{ 
       username: inc.username, 
       password: inc.password, 
     } 

     for _, s := range inc.songs { 
       outgoingRequest.songs = append(
         outgoingRequest.songs, OutgoingSong{ 
           musician: s.artist, 
           record: s.album, 
           name:  s.title, 
         }, 
       ) 
     } 

     return outgoingRequest 
} 

Così ho potrebbe colpire l'applicazione in esecuzione su localhost:8080 con qualcosa di simile:

curl -X POST http://localhost:8080/songs/new --data \ 
'{"username": "<my-username>", "password": "<my-password>", "songs": \ 
["artist": "<song-artist>", "title": "<song-title>", "album": "<song-album>"]}' 

la mia domanda è: Come faccio a scrivere i test che mettono alla prova che la richiesta che esce (in questo caso per http://www.coolsongssite.api) è corretta, senza atto mandandolo via?

Devo riscrivere il gestore createSong in modo da poter isolare ciò che accade in client.Do(request)?

Qualsiasi aiuto/consiglio/punto nella giusta direzione sono apprezzati.

Qui posso testare incomingRequestToOutgoingRequest in questo modo:

package main 

import (
     "testing" 
) 

func TestincomingRequestToOutgoingRequest(t *testing.T) { 
     incomingRequest := IncomingRequest{ 
       username: "myuser", 
       password: "mypassword", 
     } 

     var songs []IncomingSong 
     songs = append(
       songs, IncomingSong{ 
       artist: "White Rabbits", 
       album: "Milk Famous", 
       title: "I'm Not Me", 
       }, 
     ) 

     outgoingRequest := incomingRequestToOutgoingRequest(incomingRequest) 

     if outgoingRequest.songs[0].musician != "White Rabbits" { 
       t.Error("Expected musican name to be 'White Rabbits'. Got: ", outgoingRequest.songs[0].musician) 
     } 
} 

risposta

7

È possibile utilizzare net/http/httptest.NewServer come questo:

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
    w.Write([]byte(`desired response here`)) 
})) 
defer ts.Close() 
ThirdPartyAPI = ts.URL 
... 
your test here 
+1

Grazie! Questo è quello che stavo cercando. –

Problemi correlati