revelには,e2eテストのようなtest機能があるのだが、
これをgojiでも同じようなことをやりたいとき。
main.go
package main
import (
"fmt"
"net/http"
"github.com/zenazn/goji"
"github.com/zenazn/goji/web"
)
func main() {
serve()
}
func serve() {
goji.Get("/", func(c web.C, w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"foo":"bar"}`)
})
goji.Serve()
}
上みたいな場合、テストの前にgoji.Serve()
をgoroutineで起動してからテストを実行する。
main_test.go
package main
import (
"encoding/json"
"flag"
"net"
"net/http"
"os"
"testing"
"time"
)
const bind = ":11251"
// テストを走らせる前に、goji.Serve()を起動する
func TestMain(m *testing.M) {
flag.Set("bind", bind)
go func() {
serve()
}()
ready()
os.Exit(m.Run())
}
// サーバー側のport確認
func ready() {
timeout := make(chan struct{}, 1)
go func() {
time.Sleep(10 * time.Second)
timeout <- struct{}{}
}()
for {
select {
case <-time.After(100 * time.Millisecond):
if _, err := net.Dial("tcp", "127.0.0.1"+bind); err == nil {
return
}
case <-timeout:
panic("timeout")
}
}
}
// リクエストを投げて、結果のJSONが正しいかを確認する
func TestHome(t *testing.T) {
resp, err := http.Get("http://127.0.0.1" + bind)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
var ms map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&ms); err != nil {
t.Fatal(err)
}
if ms["foo"] != "bar" {
t.Errorf("foo: have %v; want bar", ms["foo"])
}
}
これでgo test
でテスト実行できる。