##はじめに
とりあえずsourcegraph.com/githubをみてください。この記事は、先程みてもらったコードの一部を紹介します。
golang+ginで簡単なテストを書いてみます。
テストは難しい
##参考にしたもの
-
ginに書いてあるテストを真似して書きました。
sourcegraph.com/github -
公式
GoDoc
##環境
go version go1.13.8 linux/amd64
##コード
main.goをつくる。
http://localhost:8080/ping
に接続すると"pong"が返ってきます。/ps(post)にして{"name":"someone"}にすると、"someone"メッセージが返ってきます。エラーのときは、"error"が返ってきます。
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Name string `json:"name" binding:"required"`
}
func router() *gin.Engine {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
// const StatusOK untyped int = 200
// gin.Hはmap[string]interface{}と同じ
c.JSON(http.StatusOK, gin.H{"msg": "pong"})
})
r.POST("/ps", func(c *gin.Context) {
var u User
if err := c.BindJSON(&u); err != nil {
// const StatusUnauthorized untyped int = 401
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "error"})
return
}
c.JSON(http.StatusOK, gin.H{"msg": u})
})
return r
}
func main() {
router().Run()
}
##テストしよう
公式通りのテストです。
func TestPingRouter(t *testing.T) {
router := router()
w := httptest.NewRecorder()
//c, _ := gin.CreateTestContext(w)
req, _ := http.NewRequest("GET", "/ping", nil)
router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
// ...
assert.Equal(t, w.Body.String(), "{\"msg\":\"pong\"}")
}
次は、POSTのテストです。
このテストは、"foo"を送ります。そうすると、JSONで返ってきます。そして、"foo"かどうかチェックします。合っていれば、テスト成功です。assert.Equal()をどんどん追加していろいろと試してみると面白そうです。
(補足)
c.Request, _ = http.NewRequest() -> context_test.goの書き方。
req, _ := http.NewRequest() -> ginのチュートリアル的なところの書き方
reqとc.Requestは多分同じで、2つとも*Requestでした。
func TestPs(t *testing.T) {
router := router()
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
body := bytes.NewBufferString("{\"name\":\"foo\"}")
c.Request, _ = http.NewRequest("POST", "/ps", body)
// req, _ := http.NewRequest("POST", "/ps", body)
router.ServeHTTP(w, c.Request)
assert.JSONEq(t, w.Body.String(), "{\"msg\":{\"name\":\"foo\"}}")
assert.Equal(t, w.Code, 200)
// ...
}
context_test.goにあるものとほとんど同じ
func TestPs2(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
body := bytes.NewBufferString("{\"foo\":\"bar\",\"bar\":\"foo\"}")
c.Request, _ = http.NewRequest("POST", "/ps", body)
c.Request.Header.Add("Content-Type", binding.MIMEJSON)
var obj struct {
Foo string `json:"foo"`
Bar string `json:"bar"`
}
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": "error"})
assert.Equal(t, w.Code, 401)
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
assert.NoError(t, c.BindJSON(&obj))
assert.Equal(t, obj.Foo, "bar")
assert.Equal(t, obj.Bar, "foo")
assert.NotEqual(t, obj.Foo, "xxxx")
assert.Empty(t, c.Errors)
}
テスト1は/ping(GET)のテストでテスト2とテスト3は/ps(POST)のテストです。
##おわり
main.goにあるBindJSONについては ginのBindingとValidationについての調査メモ