この記事は、Go2 Advent Calendar 2017の15日目の記事です。
最初に
Go言語のHTTPサーバに対してテストを実装する方法を簡単にですがご紹介したいと思います。
今回はサーバ側の実装としてechoを利用していますが、他のフレームワークを利用していても同様にテストすることが可能です。
今回のテスト対象のHTTPサーバは以下の通りです。
package main
import (
"net/http"
"github.com/labstack/echo"
)
const helloMessage = "Hello, World!"
func main() {
router := NewRouter()
router.Start(":8080")
}
func NewRouter() *echo.Echo {
e := echo.New()
e.GET("/hello", helloHandler)
return e
}
func helloHandler(c echo.Context) error {
return c.String(http.StatusOK, helloMessage)
}
HTTPリクエストをシミュレートしてテスト
HandlerFuncに対してServeHTTP(w ResponseWriter, r *Request)
を使うことで実際にサーバを立ち上げずにリクエストをシミュレートすることが可能です。
httptest.NewRequest(method, target string, body io.Reader)でクライアント側をシミュレートし、httptest.NewRecorder()で生成するレコーダーでレスポンスを記録することが可能です。
package main
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelloHandler(t *testing.T) {
router := NewRouter()
req := httptest.NewRequest("GET", "/hello", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, helloMessage, rec.Body.String())
}
実際にHTTPリクエストを飛ばしてテスト (E2E test)
サーバ部分をhttptest.NewServer(handler http.Handler)
でhttptest.Server
に置き換えてテストを行います。
httptest.Server
はテスト時に、net.Listen("tcp", "127.0.0.1:0")
でloopbackの空いている適当なポートをListenしてくれます。
尚、Listenしたいポートを固定化したい場合はgo test -httptest.serve=127.0.0.1:8000
と実行することで固定化することも可能です。
package main
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
client := new(http.Client)
func TestRouter(t *testing.T) {
router := NewRouter()
testServer := httptest.NewServer(router)
defer testServer.Close()
req, _ := http.NewRequest("GET", testServer.URL+"/hello", nil)
resp, _ := client.Do(req)
respBody, _ := ioutil.ReadAll(resp.Body)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, helloMessage, string(respBody))
}
httptest.Server
をHTTPSサーバとして立ち上げてテストしたいときは、httptest.NewTLSServer(router)
とすることでHTTPSサーバとして立ち上げることができます。
最後に
今回はecho
ベースのサーバに対してテストを行いましたが、gin
やgoji
等のフレームワークでも同様にテストすることが可能です。
それでは、良いテストライフを!