首页 >后端开发 >Golang >如何使用 `httptest` 包在 Go 中对 HTTP 调用进行单元测试?

如何使用 `httptest` 包在 Go 中对 HTTP 调用进行单元测试?

Susan Sarandon
Susan Sarandon原创
2024-12-13 16:21:10567浏览

How to Unit Test HTTP Calls in Go using the `httptest` Package?

如何使用 httptest 在 Go 中测试 HTTP 调用

简介

单元测试是软件开发的一个重要方面,对于 Go 程序来说,httptest 包提供了一个用于测试 HTTP 调用的有用工具。本文将演示如何使用 httptest 为发出 HTTP 请求的 Go 代码编写单元测试。

挑战

考虑以下 Go 代码:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "time"
)

type twitterResult struct {
    Results []struct {
        Text     string `json:"text"`
        Ids      string `json:"id_str"`
        Name     string `json:"from_user_name"`
        Username string `json:"from_user"`
        UserId   string `json:"from_user_id_str"`
    }
}

var (
  twitterUrl = "http://search.twitter.com/search.json?q=%23UCL"
  pauseDuration = 5 * time.Second
)

func retrieveTweets(c chan<- *twitterResult) {
    for {
        resp, err := http.Get(twitterUrl)
        if err != nil {
            log.Fatal(err)
        }

        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        r := new(twitterResult) //or &amp;twitterResult{} which returns *twitterResult
        err = json.Unmarshal(body, &amp;r)
        if err != nil {
            log.Fatal(err)
        }
        c <- r
        time.Sleep(pauseDuration)
    }

}

func displayTweets(c chan *twitterResult) {
    tweets := <-c
    for _, v := range tweets.Results {
        fmt.Printf("%v:%v\n", v.Username, v.Text)
    }

}

func main() {
    c := make(chan *twitterResult)
    go retrieveTweets(c)
    for {
        displayTweets(c)
    }

}

目标是为此代码编写单元测试,重点是测试从 Twitter 搜索中检索推文所发出的 HTTP 请求API.

使用 httptest 的解决方案

httptest 包提供两种类型的测试:响应测试和服务器测试。对于这种场景,服务器测试更合适。操作步骤如下:

  1. 创建测试服务器:
func TestRetrieveTweets(t *testing.T){
    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintln(w, `{"fake twitter json string"}`)
    }))
    defer ts.Close()

此代码创建一个测试服务器,该服务器使用预定义的 JSON 响应。

  1. 更新原始内容代码:
twitterUrl = ts.URL

在原始代码中,twitterUrl 变量被修改为指向测试服务器的 URL,而不是实际的 Twitter API 端点。

  1. 创建一个Channel:
c := make(chan *twitterResult)

原代码中,channel 用于测试 goroutine 和 main goroutine 之间进行通信。

  1. 启动一个要检索的 Goroutine推文:
go retrieveTweets(c)

此 goroutine 启动从测试服务器检索推文的过程。

  1. 接收推文:
tweet := <-c
if tweet != expected1 {
    t.Fail()
}

tweet = <-c
if tweet != expected2 {
    t.Fail()
}

测试 goroutine 接收来自频道的推文并检查它们是否与预期结果匹配。

进一步注意事项

值得注意的是,测试并未验证 HTTP 响应的内容。为了进行更彻底的测试,有必要将实际响应与预期响应进行比较。此外,测试服务器应该返回更真实的响应结构,以准确模拟实际的 Twitter API。

以上是如何使用 `httptest` 包在 Go 中对 HTTP 调用进行单元测试?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn