httptest를 사용하여 Go에서 http 호출을 테스트하는 방법
다음 코드가 있습니다.
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)
}
}
나는 그것을위한 몇 가지 테스트를 작성하고 싶습니다,하지만 난 확실히 httptest 패키지를 사용하는 방법을 모르겠어요 http://golang.org/pkg/net/http/httptest/을 몇 가지 포인터를 부탁드립니다
나는 이것을 생각 해냈다 (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는 응답과 서버라는 두 가지 유형의 테스트를 수행합니다.
응답 테스트 :
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)
}
}
}
서버 테스트 (사용해야하는 것) :
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, 이미 포인터이기 때문에 r의 포인터를 전달할 필요가 없습니다.
err = json.Unmarshal(body, r)
편집 : 내 레코더 테스트를 위해 다음과 같이 http 처리기를 사용할 수 있습니다.
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
Originally this code snippet was found on GitHub Gist, but while trying to apply the concept to one of my projects I realized that I had to modify the main code significantly that I decided to test these calls using an integration test by using docker and curl.
If you want to test your program, it is often best to write it with testing in mind. For instance, if you extracted the inner loop of your retrieveTweets
function into something like this:
func downloadTweets(tweetsUrl string) (*twitterResult, error)
You could invoke it with the URL of a test server you've set up using the httptest
package without having to worry about the sleeps or repeated requests.
참고URL : https://stackoverflow.com/questions/16154999/how-to-test-http-calls-in-go-using-httptest
'Program Tip' 카테고리의 다른 글
Java가 SSL 핸드 셰이크 중에 클라이언트 인증서를 보내지 않는 이유는 무엇입니까? (0) | 2020.12.01 |
---|---|
현재 준비되었거나 커밋 된 git에서 무시한 파일을 나열하는 방법은 무엇입니까? (0) | 2020.12.01 |
for 또는 while없이 생성자의 무한 루프 (0) | 2020.12.01 |
localstorage (또는 다른 곳)에서 ES6 맵을 유지하려면 어떻게해야합니까? (0) | 2020.12.01 |
pylint logging-not-lazy를 수정하는 방법은 무엇입니까? (0) | 2020.12.01 |