如何使用httptest测试http调用 [英] How to test http calls in go using httptest

查看:117
本文介绍了如何使用httptest测试http调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

 包主

导入(
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)
}
}
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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆