这篇“Golang httptest包测试如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Golang httptest包测试如何使用”文章吧。
下面通过示例介绍http server的测试。首先看http服务程序,把请求字符串转为大写:
package main import ( "fmt" "log" "net/http" "net/url" "strings" ) // Req: http://localhost:1234/upper?word=abc // Res: ABC func 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逻辑,我们需要准备两方面:
使用httptest.NewRequest暴露的函数创建http.Request对象,NewRequest返回Request, 可以传给http.Handler进行测试.
使用httptest.NewRecorder函数创建http.ResponseWriter,返回httptest.ResponseRecorder。ResponseRecorder是
http.ResponseWriter 的实现,它记录变化为了后面测试检查.
httptest.ResponseRecorder是 http.ResponseWriter 的实现,可以传给http server handle,记录所有处理并写回响应的数据,下面测试程序可以看到其如何实现:
package main import ( "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.ResponseWriter 和 http.Request对象。对于HTTP客户端测试,情况稍晚有点复杂。原因是有时不容易模拟或复制整个HTTP Server,请看下面示例:
package main import ( "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.NewServer函数生成我们想要的 httptest.Server。表示http服务,监听回环地址及可选的端口号,用于实现端到端HTTP测试。
func NewServer(handler http.Handler) *Server
NewServer 启动并返回新的HTTP服务,调用者使用完成后应该调用Close方法结束服务。下面通过示例进行解释:
package main import ( "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 response res = strings.TrimSpace(res) if res != expected { t.Errorf("expected res to be %s got %s", expected, res) } }
以上就是关于“Golang httptest包测试如何使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。