Go
golang

net/httptestでgojiのテストをする

More than 3 years have passed since last update.

goji でWebアプリを書こうとしています。APIサーバーとして使うときに、テストが気になります。

golangは net/http/httptest

というhttpのtestを行うパッケージが最初からついています。これを使うと簡単にテストを記述できます。

httptest.Serverはlocalのloopbackインタフェースでサーバーを作成します。

(2014/11/20追記): mopemopeさんから「Routingのテストを入れたほうがいいのでは」というご指摘を受けたので、Route設定を別関数に分け、テストからも使うようにしました。


サンプルアプリ

/hello/hoge というURLにアクセスが来たらJSONを返す、という単純なアプリです。


main.go

package main

import (
"encoding/json"
"fmt"
"net/http"

"github.com/zenazn/goji"
"github.com/zenazn/goji/web"
)

type User struct {
Id int64
Name string
}

func hello(c web.C, w http.ResponseWriter, r *http.Request) {
u := User{
Id: 1,
Name: c.URLParams["name"],
}

j, _ := json.Marshal(u)
fmt.Fprintf(w, string(j))
}

func Route(m *web.Mux) {
m.Get("/hello/:name", hello)
}

func main() {
Route(goji.DefaultMux)
goji.Serve()
}


これに対するテストが以下の感じです。


main_test.go

package main

import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/zenazn/goji/web"
)

func ParseResponse(res *http.Response) (string, int) {
defer res.Body.Close()
contents, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
return string(contents), res.StatusCode
}

func Test_Hello(t *testing.T) {
m := web.New()
Route(m)
ts := httptest.NewServer(m)
defer ts.Close()

res, err := http.Get(ts.URL + "/hello/hoge")
if err != nil {
t.Error("unexpected")
}
c, s := ParseResponse(res)
if s != http.StatusOK {
t.Error("invalid status code")
}
if c != `{"Id":1,"Name":"hoge"}` {
t.Error("invalid response")
}
}


web.New() でgoji/webのHTTP multiplexerを作成します。あとは、httptest.NewServer(m)としてあげれば、テスト用サーバーが立ち上がります。deferでCloseするのを忘れないでください。

なお、ts.URLには、立ち上げたテスト用サーバーのportが入ったURLがhttp://127.0.0.1:51923 みたいな感じで入っています。

簡単にするためにParseResponseという関数を作っていますが、これは別になくても構いません。

もっと他にいい方法があれば教えてください。