Web开发人员的工作很大一部分涉及API调用,无论是与合作伙伴系统集成还是与供应商集成。
编写测试是开发流程中不可或缺的一部分。测试确保代码按预期工作,避免在生产环境中出现意外情况。 熟练掌握API测试对于合格的软件工程师至关重要。本文将介绍几种简化API功能测试的技术。
首先,我们需要构建一个待测试的服务。这是一个简单的例子:我们调用Pokédex API(受Pokémon TCG Pocket的启发)并列出现有的。
package main import ( "encoding/json" "fmt" "net/http" ) type RespBody struct { Results []Pokemon `json:"results"` } type Pokemon struct { Name string `json:"name"` } const URL = "https://pokeapi.co" func main() { pkms, err := FetchPokemon(URL) if err != nil { fmt.Println(err) return } for _, pkm := range pkms { fmt.Println(pkm.Name) } } func FetchPokemon(u string) ([]Pokemon, error) { r, err := http.Get(fmt.Sprintf("%s/api/v2/pokemon", u)) if err != nil { return nil, err } defer r.Body.Close() resp := RespBody{} err = json.NewDecoder(r.Body).Decode(&resp) if err != nil { return nil, err } return resp.Results, nil }
httptest
httptest是Go语言自带的包。它允许在测试中创建模拟服务器。其主要优点是不需要引入外部依赖。但它不会自动拦截请求。
package main import ( "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" ) func Test_httptest(t *testing.T) { j, err := json.Marshal(RespBody{Results: []Pokemon{{Name: "charizard"}}}) assert.Nil(t, err) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v2/pokemon" { t.Errorf("expected to request '/api/v2/pokemon', got: %s", r.URL.Path) } w.WriteHeader(http.StatusOK) w.Write([]byte(j)) })) defer server.Close() p, err := FetchPokemon(server.URL) assert.Nil(t, err) assert.Equal(t, p[0].Name, "charizard") }
Mocha
Mocha是一个受Nock和Wires启发的库。一个有趣的功能是能够验证模拟是否被调用。与httptest类似,它也不会自动拦截请求。
package main import ( "encoding/json" "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/vitorsalgado/mocha/v3" "github.com/vitorsalgado/mocha/v3/expect" "github.com/vitorsalgado/mocha/v3/reply" ) func Test_mocha(t *testing.T) { j, err := json.Marshal(RespBody{Results: []Pokemon{{Name: "charizard"}}}) assert.Nil(t, err) m := mocha.New(t) m.Start() scoped := m.AddMocks(mocha.Get(expect.URLPath("/api/v2/pokemon")). Reply(reply.OK().BodyString(string(j)))) p, err := FetchPokemon(m.URL()) fmt.Println(m.URL()) assert.Nil(t, err) assert.True(t, scoped.Called()) assert.Equal(t, p[0].Name, "charizard") }
Gock
Gock是另一个不错的选择,它也是一个受Nock启发的库,具有简洁易用的API。它能够拦截任何http.Client发出的HTTP请求,并提供验证模拟调用的机制。如果模拟不存在,则返回错误;如果启用实际网络模式,则请求正常进行。
package main import ( "encoding/json" "testing" "github.com/h2non/gock" "github.com/stretchr/testify/assert" ) func Test_gock(t *testing.T) { defer gock.Off() j, err := json.Marshal(RespBody{Results: []Pokemon{{Name: "charizard"}}}) assert.Nil(t, err) gock.New("https://pokeapi.co"). Get("/api/v2/pokemon"). Reply(200). JSON(j) p, err := FetchPokemon(URL) assert.Nil(t, err) assert.Equal(t, p[0].Name, "charizard") }
apitest
最后,apitest是一个受Gock启发的库,具有丰富的匹配器和功能。它甚至允许生成HTTP调用的序列图。一个很酷的特性是它有一个很棒的网站,其中包含示例。
package main import ( "encoding/json" "net/http" "testing" "github.com/steinfletcher/apitest" "github.com/stretchr/testify/assert" ) func Test_APItest(t *testing.T) { j, err := json.Marshal(RespBody{Results: []Pokemon{{Name: "Charizard"}}}) assert.Nil(t, err) defer apitest.NewMock(). Get("https://pokeapi.co/api/v2/pokemon"). RespondWith(). Body(string(j)). Status(http.StatusOK). EndStandalone()() p, err := FetchPokemon(URL) assert.Nil(t, err) assert.Equal(t, p[0].Name, "Charizard") }
总结
我认为没有哪个库绝对优于其他库,选择取决于你的偏好和项目需求。如果你不想引入额外的依赖,并且不介意手动编写匹配器,那么httptest是一个不错的选择。如果你需要更丰富的API或更全面的功能,可以考虑其他库。 我个人非常喜欢apitest,并推荐在团队中使用它,因为它功能非常全面。
更多示例请访问[链接] (此处应插入实际链接)。
以上就是以最佳方式对API进行测试的详细内容,更多请关注php中文网其它相关文章!