やりたいこと
外部API叩くようなプログラムを書いていてインテグレーションテストのためにHTTPモックサーバがほしい(Rubyのwebmock, javaのWireMockみたいな感じ)。
解決法
GO言語にそれ用のいいライブラリはない。
httpmockはまさにこの目的のためのライブラリだが、このライブラリを使用するとnet/httpを使った接続をすべて奪いとってしまう。具体的には一度モックを作成するとそのURL以外へアクセスしようとするとエラーが出る。
定義したURLへのアクセスのみモックするようなオプションは今のところないようだ。
そこで、純粋にモック用途のhttpサーバが立てばいいだけのケースでは標準ライブラリのhttptestを使う。
func TestWithMockedServer(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
}))
defer ts.Close()
// ここにモックサーバーを利用したテストを記述。ポート番号は自動で決定されるので ts.URLで取得
}
httptestのポート自動決定は便利だがポートを指定する必要がある場合はこう書く。
func TestWithMockedServer(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
})
l, _ := net.Listen("tcp", ":8080")
ts := httptest.Server{
Listener: l,
Config: &http.Server{Handler: handler},
}
ts.Start()
defer ts.Close()
// ここにモックサーバーを利用したテストを記述。ポート番号は8080で固定
}
httptestを用いた時の欠点はそのモックしたAPIの呼び出し回数などをチェックできないことである(モックではなくスタブ的になる)。
蛇足
ローンパターンを用いて関数化するとスマートになるが、golangの文化と合っているかわからない。