文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Golang httptest包测试如何使用

2023-07-05 12:42

关注

这篇“Golang httptest包测试如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Golang httptest包测试如何使用”文章吧。

测试http服务端处理器

下面通过示例介绍http server的测试。首先看http服务程序,把请求字符串转为大写:

package mainimport (    "fmt"    "log"    "net/http"    "net/url"    "strings")// Req: http://localhost:1234/upper?word=abc// Res: ABCfunc upperCaseHandler(w http.ResponseWriter, r *http.Request) {    query, err := url.ParseQuery(r.URL.RawQuery)    if err != nil {        w.WriteHeader(http.StatusBadRequest)        fmt.Fprintf(w, "invalid request")        return    }    word := query.Get("word")    if len(word) == 0 {        w.WriteHeader(http.StatusBadRequest)        fmt.Fprintf(w, "missing word")        return    }    w.WriteHeader(http.StatusOK)    fmt.Fprintf(w, strings.ToUpper(word))}func main() {    http.HandleFunc("/upper", upperCaseHandler)    log.Fatal(http.ListenAndServe(":1234", nil))}

现在想测试http server使用的upperCaseHandler逻辑,我们需要准备两方面:

http.ResponseWriter 的实现,它记录变化为了后面测试检查.

httptest.ResponseRecorder

httptest.ResponseRecorder是 http.ResponseWriter 的实现,可以传给http server handle,记录所有处理并写回响应的数据,下面测试程序可以看到其如何实现:

package mainimport (    "io/ioutil"    "net/http"    "net/http/httptest"    "testing")func TestUpperCaseHandler(t *testing.T) {    req := httptest.NewRequest(http.MethodGet, "/upper?word=abc", nil)    w := httptest.NewRecorder()    upperCaseHandler(w, req)    res := w.Result()    defer res.Body.Close()    data, err := ioutil.ReadAll(res.Body)    if err != nil {        t.Errorf("expected error to be nil got %v", err)    }    if string(data) != "ABC" {        t.Errorf("expected ABC got %v", string(data))    }}

上面示例中首先定义请求和响应,然后传入处理器进行测试。然后检查ResponseRecorder的Result方法输出:

func (rw *ResponseRecorder) Result() *http.Response

Result返回处理器生成的响应。返回相应至少有StatusCode, Header, Body, 以及可选其他内容,未来可能会填充更多字段,所以调用者在测试中不应该深度比较相等。

测试HTTP客户端

测试服务端处理器相对容易,特别当测试处理器逻辑时,仅需要在测试中模拟http.ResponseWriter 和 http.Request对象。对于HTTP客户端测试,情况稍晚有点复杂。原因是有时不容易模拟或复制整个HTTP Server,请看下面示例:

package mainimport (    "io/ioutil"    "net/http"    "github.com/pkg/errors")type Client struct {    url string}func NewClient(url string) Client {    return Client{url}}func (c Client) UpperCase(word string) (string, error) {    res, err := http.Get(c.url + "/upper?word=" + word)    if err != nil {        return "", errors.Wrap(err, "unable to complete Get request")    }    defer res.Body.Close()    out, err := ioutil.ReadAll(res.Body)    if err != nil {        return "", errors.Wrap(err, "unable to read response data")    }    return string(out), nil}

client需要url,表示远程服务端基地址。然后调用/upper,带上输入单词,最后返回结果字符串给调用者,如果调用不成功还返回错误对象。为了测试这段代码,需要模拟整个http服务端逻辑,或至少是响应请求路径:/upper。使用httptest包可以模拟整个http 服务,通过初始化本地服务,监听回环地址并返回你想要的任何内容。

使用 httptest.Server

通过调用httptest.NewServer函数生成我们想要的 httptest.Server。表示http服务,监听回环地址及可选的端口号,用于实现端到端HTTP测试。

func NewServer(handler http.Handler) *Server

NewServer 启动并返回新的HTTP服务,调用者使用完成后应该调用Close方法结束服务。下面通过示例进行解释:

package mainimport (    "fmt"    "net/http"    "net/http/httptest"    "strings"    "testing")func TestClientUpperCase(t *testing.T) {    expected := "dummy data"    svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        fmt.Fprintf(w, expected)    }))    defer svr.Close()    c := NewClient(svr.URL)    res, err := c.UpperCase("anything")    if err != nil {        t.Errorf("expected err to be nil got %v", err)    }    // res: expected\r\n    // due to the http protocol cleanup response    res = strings.TrimSpace(res)    if res != expected {        t.Errorf("expected res to be %s got %s", expected, res)    }}

上面示例中使用httptest.NewServer函数创建了模拟http服务器,给它传入自定义模拟处理器,总是返回相同的数据。并使用服务端url作为客户端请求url,从而模拟并让服务端返回任何我们想测试的内容。

当然我们可以修改处理器,让其返回我们期望的逻辑:

func TestClientUpperCase(t *testing.T) {svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {query, err := url.ParseQuery(r.URL.RawQuery)if err != nil {w.WriteHeader(http.StatusBadRequest)fmt.Fprintf(w, "invalid request")return}word := query.Get("word")if len(word) > 0 {fmt.Fprintf(w, strings.ToUpper(word))} else {fmt.Fprintf(w, "no input")}}))defer svr.Close()expected := "ANYTHING"c := NewClient(svr.URL)res, err := c.UpperCase("anything")if err != nil {t.Errorf("expected err to be nil got %v", err)}// res: expected\r\n// due to the http protocol cleanup responseres = strings.TrimSpace(res)if res != expected {t.Errorf("expected res to be %s got %s", expected, res)}}

以上就是关于“Golang httptest包测试如何使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯