我正在开发一个在内部后端和多个第三方 API 之间进行转换的 Go API。我试图了解如何在不实际访问外部 API 的情况下测试其功能。
例如,这是一个服务器,它处理传入的制作新歌曲的请求,并将请求发送到第三方 API:
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
}
所以我可能会用这样的东西来访问在 localhost:8080
上运行的应用程序:
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>"]}'
我的问题是:
如何编写测试来测试发出的请求(在本例中为 http://www.coolsongssite.api
)是否正确,而不实际发送它?
我是否应该重写 createSong
处理程序以便隔离 client.Do(request)
中发生的事情?
任何正确方向的帮助/建议/要点都将受到赞赏。
在这里,我可以像这样测试 incomingRequestToOutgoingRequest
:
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)
}
}
最佳答案
您可以像这样使用 net/http/httptest.NewServer
:
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte(`desired response here`))
}))
defer ts.Close()
ThirdPartyURL = ts.URL
...
your test here
每当您的代码对 ThirdPartyURL
执行 HTTP 调用时,您将在定义的处理程序中收到请求,并可以返回您需要的任何响应。
关于api - 在不实际访问第三方 API 的情况下测试 Go (Golang) API 传出请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38339541/