如何测试在Go中调用另一个API端点的服务?
我使用无限循环创建了一个简单的服务,定期调用特定的HTTP API,在包如何测试在Go中调用另一个API端点的服务?,go,tdd,bdd,Go,Tdd,Bdd,我使用无限循环创建了一个简单的服务,定期调用特定的HTTP API,在包aservice中实现。我在那里创建了一个服务结构。通常,为了运行该服务,我公开了一个用于同步运行该服务的StartService方法。然后,包的用户可以使用goroutine运行它。我的问题是,如何为这种场景编写测试 您是否运行整个系统并“模拟”API?我听说使用第三方服务的代码不需要测试,但是整个aservice包可能只包含StartService和Shutdown方法。其余的是未报告的函数/方法,因此无法单独测试。如果
aservice
中实现。我在那里创建了一个服务结构。通常,为了运行该服务,我公开了一个用于同步运行该服务的StartService
方法。然后,包的用户可以使用goroutine运行它。我的问题是,如何为这种场景编写测试
您是否运行整个系统并“模拟”API?我听说使用第三方服务的代码不需要测试,但是整个aservice
包可能只包含StartService
和Shutdown
方法。其余的是未报告的函数/方法,因此无法单独测试。如果是这样的话,那么我就根本无法编写任何测试了?使用Go,您在模拟外部http请求时会有很棒的体验。长话短说,用net/http/httptest包中的服务器url替换基本url。
您可以模仿Google模拟其外部请求的方式,例如在Google地图中搜索测试
你在测试什么?您是否正在测试从API获得的响应是否得到正确处理?如果是这样,您可以提取将API输出处理为未报告函数的逻辑,并为这些函数编写测试。如果您正在测试对API的调用是否准备正确?然后模拟API并测试请求。是的,我实际上是想测试两者。但我认为这里的问题更多的是API模拟。你的评论只是给了我一个关于测试场景的答案。也许给我一个关于模拟部分的细节?如果您模拟了API,这意味着您需要单独启动一台服务器,对吗?对于并行测试来说,这不是有点混乱吗?您可以使用net/http/httptest包使用测试服务器模拟它。或者,您可以在没有HTTP位的情况下模拟API调用,方法是将HTTP部分重构为一个结构,并在httptest包的测试过程中传递该结构的单独实现,这样我就不必生成单独的服务器了,对吗?如果我必须生成一个单独的虚拟服务器,那么使用CI服务器运行它就有点复杂了。这种测试仍然称为单元测试?还是行为测试?
server := mockServer(200, response)
defer server.Close()
c, _ := NewClient(WithAPIKey(apiKey), WithBaseURL(server.URL))
r := &DirectionsRequest{
Origin: "Google Sydney",
Destination: "Glebe Pt Rd, Glebe",
Mode: TravelModeTransit,
}
resp, _, err := c.Directions(context.Background(), r)
// your assertions goes here
// Create a mock HTTP Server that will return a response with HTTP code and body.
func mockServer(code int, body string) *httptest.Server {
server := mockServerForQuery("", code, body)
return server.s
}
func mockServerForQuery(query string, code int, body string) *countingServer {
server := &countingServer{}
server.s = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if query != "" && r.URL.RawQuery != query {
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(query, r.URL.RawQuery, false)
log.Printf("Query != Expected Query: %s", dmp.DiffPrettyText(diffs))
server.failed = append(server.failed, r.URL.RawQuery)
http.Error(w, "fail", 999)
return
}
server.successful++
w.WriteHeader(code)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
fmt.Fprintln(w, body)
}))
return server
}