はじめに
ginのmiddlewareのunitテストをしようと思ったときにちょっとハマったので備忘録としてまとめておきます
テスト内容
まずはソースツリーから
├── main.go
└── middleware
├── auth.go
└── auth_test.go
シンプルにGinのクイックスタートにmiddleware.Authorizationを噛ましてるだけです
package main
import (
"testing_gin_context/middleware"
"github.com/gin-gonic/gin"
)
func setupRouter() *gin.Engine {
r := gin.Default()
// 認証用のmiddlewareを使用
r.Use(middleware.Authorization)
r.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
return r
}
func main() {
r := setupRouter()
r.Run(":8080")
}
contextからヘッダー情報を取得し、トークンが取得できれば認証を行い、その結果をcontextに詰めて返しています。
package middleware
import (
"github.com/gin-gonic/gin"
)
func Authorization(c *gin.Context) {
// リクエストヘッダーからaccessTokenを取得
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, JSONオブジェクト)
return
}
/*
何かしらの認証を行う・・・
*/
// 認証の結果をcontextに詰める
c.Set("userId", "1234567890")
c.Set("userName", "Taro")
c.Next()
}
package middleware
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func TestAuthorization(t *testing.T) {
// gin contextの生成
ginContext, _ := gin.CreateTestContext(httptest.NewRecorder())
// リクエストの生成
// 今回はmiddlewareのテストのためpathはなんでも可
req, _ := http.NewRequest("GET", "/", nil)
// ヘッダー情報の追加
req.Header.Add("Authorization", "AccessToken")
// リクエスト情報をコンテキストに入れる
ginContext.Request = req
// Authorization関数を実行
authMiddleware.Authorization(ginContext)
asserts := assert.New(t)
asserts.Equal("userId", c.GetString("1234567890"))
asserts.Equal("userName", c.GetHeader("Taro"))
}
テストのポイント
ポイントとしては
// gin contextの生成
ginContext, _ := gin.CreateTestContext(httptest.NewRecorder())
// リクエスト情報をコンテキストに入れる
ginContext.Request = req
の2箇所あたりだと思います。
実はこのCreateTestContext
どうやら以前は返り値を3つ返していたことがあるらしく、かなりいろんなところで↓のような記述を見たのですが、どうやらバージョンが変わって今の形になったっぽいです(たぶんw)
(参考文献: https://godoc.org/github.com/gin-gonic/gin#CreateTestContext )
c, _, _ := gin.CreateTestContext()
またgin.Context自身は
// 公開されているフィールドのみ記述
type Context struct {
Request *http.Request
Writer ResponseWriter
Params Params
handlers HandlersChain
Errors errorMsgs
Accepted []string
}
というように定義されていたので今回はRequestフィールドに直接リクエスト内容を入れてあげたような感じです。
(※ginの公式のテストを見てそのやり方を真似しましたw)
https://sourcegraph.com/github.com/gin-gonic/gin@8f3047814e86442c8efbd91ef7007905d47cf6c9/-/blob/context_test.go#L57
#参考文献