如何测试在Go中调用另一个API端点的服务?

如何测试在Go中调用另一个API端点的服务?,go,tdd,bdd,Go,Tdd,Bdd,我使用无限循环创建了一个简单的服务,定期调用特定的HTTP API,在包aservice中实现。我在那里创建了一个服务结构。通常,为了运行该服务,我公开了一个用于同步运行该服务的StartService方法。然后,包的用户可以使用goroutine运行它。我的问题是,如何为这种场景编写测试 您是否运行整个系统并“模拟”API?我听说使用第三方服务的代码不需要测试,但是整个aservice包可能只包含StartService和Shutdown方法。其余的是未报告的函数/方法,因此无法单独测试。如果

我使用无限循环创建了一个简单的服务,定期调用特定的HTTP API,在包
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
}