概要
net/http
には net/http/httptest
という標準パッケージがありこれを使えばテストを書くことができます
今回は net/http/httptest
パッケージを使ってテストを書いてみました
環境
- macOS 10.14.4
- go 1.11.5
サンプルアプリ
vim $GOPATH/src/github.com/hawksnowlog/a/main.go
package main
import (
"fmt"
"net/http"
)
func HelloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("hello")
w.Write([]byte("hello"))
}
func main() {
http.HandleFunc("/", HelloHandler)
http.ListenAndServe(":8080", nil)
}
/
にアクセスすると「hello」と返す簡単なアプリです
実際にアプリのハンドラに通っていることを確認するために fmt.Println
を記載しています
基本的なテスト
ではテストを記載します
xxx_test.go
というテストファイルを同一ディレクトリに置きましょう
vim $GOPATH/src/github.com/hawksnowlog/a/main_test.go
package main
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
)
func TestRoot(t *testing.T) {
testserver := httptest.NewServer(http.HandlerFunc(HelloHandler))
defer testserver.Close()
res, err := http.Get(testserver.URL)
if err != nil {
t.Error(err)
}
hello, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
t.Error(err)
}
if res.StatusCode != 200 {
t.Error("a response code is not 200")
}
if string(hello) != "hello" {
t.Error("a response is not hello")
}
}
go fmt github.com/hawksnowlog/a
go test github.com/hawksnowlog/a
でテスト出来ます
解説
まずはテストサーバを作成します
アプリ側で作成したハンドラを使って作成します
testserver := httptest.NewServer(http.HandlerFunc(HelloHandler))
defer testserver.Close()
ちゃんと Close するのを忘れないようにしましょう
作成したサーバに GET リクエストを送信するには http.Get
を使います
res, err := http.Get(testserver.URL)
あとは受け取ったレスポンスをチェックすれば OK です
実際にアプリを動かしてテストしても OK
実は net/http/httptest
で NewServer すると指定したハンドラを持つアプリがテスト用に立ち上がり LISTEN しています
上記の場合ただそこに http.Get
しているだけです
なので httptest
を使わずに以下のように書くこともできます
go build github.com/hawksnowlog/a
./a
で普通にアプリを立ち上げたあとに、そのアプリ目掛けて http.Get
すれば OK です
vim $GOPATH/src/github.com/hawksnowlog/a/main_test.go
package main
import (
"io/ioutil"
"net/http"
"testing"
)
func TestRoot(t *testing.T) {
res, err := http.Get("http://localhost:8080")
if err != nil {
t.Error(err)
}
hello, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
t.Error(err)
}
if res.StatusCode != 200 {
t.Error("a response code is not 200")
}
if string(hello) != "hello" {
t.Error("a response is not hello")
}
}
go test github.com/hawksnowlog/a
ハンドラを mock するには
ハンドラを mock したいのであれば単純にアプリのハンドラを使わずにテスト側でハンドラを定義すれば OK です
vim $GOPATH/src/github.com/hawksnowlog/a/main_test.go
package main
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
)
func mockHelloHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("mock hello"))
}
func TestRoot(t *testing.T) {
testserver := httptest.NewServer(http.HandlerFunc(mockHelloHandler))
defer testserver.Close()
res, err := http.Get(testserver.URL)
if err != nil {
t.Error(err)
}
hello, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
t.Error(err)
}
if res.StatusCode != 200 {
t.Error("a response code is not 200")
}
if string(hello) != "mock hello" {
t.Error("a response is not mock hello")
}
}
go test github.com/hawksnowlog/a
ハンドラ内の特定の処理だけ mock したい場合には面倒ですがその部分だけ mock したハンドラを定義すれば OK です
もしくは gomock というパッケージがあるのでこれを使って特定のメソッドを mock するという方法もあります
最後に
net/http/httpclient
を使って net/http
をテストしてみました
基本的にはテストしたいハンドラ指定したり mock してテストします
これだけでも基本的なテストは十分にできるかなと思います
0 件のコメント:
コメントを投稿