如何使用httptest测试http调用 [英] How to test http calls in go using httptest
问题描述
包主
导入(
encoding / json
fmt
io / ioutil
log
net / http
time
)
$ b $类型twitterResult结构{
结果[]结构{
文本字符串`json:文本``
Ids字符串`json:id_str`
名称字符串`json:from_user_name`
用户名字符串`json:from_user`
UserId字符串`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:=新(twitterResult) //或& twitterResult {}返回* twitterResult
err = json.Unmarshal(body,& 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)
}
}
我想为它编写一些测试,但我不确定如何使用httptest包 http://golang.org/pkg/net/http/httptest/ 会赞赏一些指针
我想出了这个(无耻地从测试中复制去OAuth https://code.google.com/p/goauth2/source/browse/oauth/oauth_test.go ):
var request = struct {
路径,查询字符串//请求
contenttype,正文字符串//响应
} {
path:/search.json?,
query:q =%23Kenya,
contenttype:application / json,
body: twitterResponse,
}
var(
twitterResponse =`{'results':'{'text':'hello','id_str':'34455w4','from_user_name' :'bob','from_user_id_str':'345424'}]}`
)
func TestRetrieveTweets(t * testing.T){
handler:= func(w http .ResponseWriter,r * http.Request){
w.Header()。Set(Content-Type,request.contenttype)
io.WriteString(w,request.body)
}
server:= httptest.NewServer(http.HandlerFunc(handler))
推迟server.Close()
resp, err:= http.Get(server.URL)
if err!= nil {
t.Fatalf(Get:%v,err)
}
checkBody(t ,resp,twitterResponse)
}
func checkBody(t * testing.T,r * http.Response,body string){
b,err:= ioutil.ReadAll(r .Body)
if err!= nil {
t.Error(reading reponse body:%v,want%q,err,body)
}
if g, w:= string(b),body; g!= w {
t.Errorf(request body mismatch:got%q,want%q,g,w)
}
}
$ c $ httptest有两种类型的测试:响应和服务器
响应测试:
func TestHeader3D(t * testing.T){
resp:= httptest .NewRecorder()
uri:=/ 3D / header /?
path:=/ home / test
unlno:=997225821
param:= make(url.Values)
param [param1] = [] string {path}
param [param2] = [] string {unlno}
req,err:= http.NewRequest(GET,uri + param.Encode (),nil)
if err!= nil {
t.Fatal(err)
}
http.DefaultServeMux.ServeHTTP(resp,req)
if p,err:= ioutil.ReadAll(resp.Body); err!= nil {
t.Fail()
} else {
if strings.Contains(string(p),Error){
t.Errorf(header响应不应该返回错误:%s,p)
} else if!strings.Contains(string(p),`expected result`){
t.Errorf(header response doen't匹配:\ n%s,p)
}
}
}
服务器测试(这是您需要使用的):
func TestIt(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()
twitterUrl = ts.URL
c:= make(chan * twitterResult)
转到retrieveTweets(c)
tweet:=< -c
如果tweet!= expected1 {
t.Fail()
}
tweet =< -c
if tweet!= expected2 {
t.Fail()
}
}
顺便说一句,你不需要传入r的指针,因为它已经是一个指针了。
err = json.Unmarshal(body,r)
编辑:对于我的记录器测试,我可以使用我的http处理程序,如下所示:
handler(resp,req)
但是我原来的代码没有使用默认的mux来自Gorilla / mux),并且我在复用器周围有一些包装,例如插入服务器日志记录,并添加请求上下文(Gorilla /上下文),所以我不得不从mux开始并调用ServeHTTP
I have the following code:
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 &twitterResult{} which returns *twitterResult
err = json.Unmarshal(body, &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)
}
}
I'd like to write some tests for it, but I'm not sure how to use the httptest package http://golang.org/pkg/net/http/httptest/ would appreciate some pointers
I came up with this (shamelessly copied from the tests for go OAuth https://code.google.com/p/goauth2/source/browse/oauth/oauth_test.go):
var request = struct {
path, query string // request
contenttype, body string // response
}{
path: "/search.json?",
query: "q=%23Kenya",
contenttype: "application/json",
body: twitterResponse,
}
var (
twitterResponse = `{ 'results': [{'text':'hello','id_str':'34455w4','from_user_name':'bob','from_user_id_str':'345424'}]}`
)
func TestRetrieveTweets(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", request.contenttype)
io.WriteString(w, request.body)
}
server := httptest.NewServer(http.HandlerFunc(handler))
defer server.Close()
resp, err := http.Get(server.URL)
if err != nil {
t.Fatalf("Get: %v", err)
}
checkBody(t, resp, twitterResponse)
}
func checkBody(t *testing.T, r *http.Response, body string) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Error("reading reponse body: %v, want %q", err, body)
}
if g, w := string(b), body; g != w {
t.Errorf("request body mismatch: got %q, want %q", g, w)
}
}
解决方案 httptest does two types of tests: response and server
Response test:
func TestHeader3D(t *testing.T) {
resp := httptest.NewRecorder()
uri := "/3D/header/?"
path := "/home/test"
unlno := "997225821"
param := make(url.Values)
param["param1"] = []string{path}
param["param2"] = []string{unlno}
req, err := http.NewRequest("GET", uri+param.Encode(), nil)
if err != nil {
t.Fatal(err)
}
http.DefaultServeMux.ServeHTTP(resp, req)
if p, err := ioutil.ReadAll(resp.Body); err != nil {
t.Fail()
} else {
if strings.Contains(string(p), "Error") {
t.Errorf("header response shouldn't return error: %s", p)
} else if !strings.Contains(string(p), `expected result`) {
t.Errorf("header response doen't match:\n%s", p)
}
}
}
Server test (which is what you need to use):
func TestIt(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()
twitterUrl = ts.URL
c := make(chan *twitterResult)
go retrieveTweets(c)
tweet := <-c
if tweet != expected1 {
t.Fail()
}
tweet = <-c
if tweet != expected2 {
t.Fail()
}
}
BTW, you don't need to pass in the pointer of r, because it's already a pointer.
err = json.Unmarshal(body, r)
EDIT: for my recorder test, I could use my http handler like this:
handler(resp, req)
But my original code is not using the default mux (but from Gorilla/mux), and I have some wrapping around the mux, e.g. insert server logging, and adding request context (Gorilla/context), so I had to start from mux and call ServeHTTP
这篇关于如何使用httptest测试http调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!