Go
test
golang
echo

EchoでSessionを利用したテストを行う

More than 1 year has passed since last update.

セッション機能の導入はこちらを参考に
https://qiita.com/to-hutohu/items/740ee30aa996c0bd8d7e

環境

  • Go1.9
  • echo 3.2.3
  • srinathgs/mysqlstore

流れ

  1. テストを行う前にセッションストアにデータを入れておく
  2. ミドルウェアを通してハンドラを返す
  3. 後は通常通り

example.go
func Handler(c echo.Context) error {
    sess, err := session.Get("sessions", c)
    if err != nil {
        return fmt.Errorf("Failed to get session: %v", err)
    }

    var userId string
    if sess.Values["userId"] != nil {
        userId = sess.Values["userId"].(string)
    }
    // 処理
}

テストコード(抜粋)

example_test.go
func beforeTest(t *testing.T) (*echo.Echo, *http.Cookie, echo.MiddlewareFunc) {
    e := echo.New()

    store, err := mysqlstore.NewMySQLStore(endpoint, 
                    "sessions", "/", 60*60*24*14, []byte("secret"))

    if err != nil {
        t.Fatal(err)
    }

    // セッション情報をあらかじめストアに保存しておく
    req := httptest.NewRequest(echo.GET, "/", nil)
    rec := httptest.NewRecorder()
    sess, err := store.New(req, "session")
    sess.Values["userId"] = "testUser"

    err = sess.Save(req, rec)
    if err != nil {
        t.Fatal(err)
    }

    // セッションIDを取得して使いまわせるようにしておく
    cookie := parseCookies(rec.Header().Get("Set-Cookie"))["session"]
    mw := session.Middleware(store)

    return e, cookie, mw
}

func TestGetChannelsHandler(t *testing.T) {
    e, cookie, mw := beforeTest(t)

    // ミドルウェアを通してハンドラの設定
    rec := request(e, t, mw(Handler), cookie)
    // レスポンスのチェック
}


func request(e *echo.Echo, t *testing.T, handler echo.HandlerFunc, cookie *http.Cookie) *httptest.ResponseRecorder {
    req := httptest.NewRequest("GET", "http://test", nil)

    req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)

    // クッキーに設定しておく
    if cookie != nil {
        req.Header.Add("Cookie", fmt.Sprintf("%s=%s", cookie.Name, cookie.Value))
    }
    rec := httptest.NewRecorder()
    c := e.NewContext(req, rec)
    err := handler(c)

    if err != nil {
        t.Fatal(err)
    }

    return rec
}

func parseCookies(value string) map[string]*http.Cookie {
    m := map[string]*http.Cookie{}
    for _, c := range (&http.Request{Header: http.Header{"Cookie": {value}}}).Cookies() {
        m[c.Name] = c
    }
    return m
}

複数のエンドポイントをテストする場合には上のようにリクエスト部分をある程度まとめておくと、コードが簡潔になりそうです。