LoginSignup
14
6

More than 3 years have passed since last update.

GO言語+ginでテストを書く

Last updated at Posted at 2020-11-02

はじめに

とりあえずsourcegraph.com/githubをみてください。この記事は、先程みてもらったコードの一部を紹介します。
golang+ginで簡単なテストを書いてみます。
テストは難しい

参考にしたもの

環境

go version go1.13.8 linux/amd64

コード

main.goをつくる。  
http://localhost:8080/ping
に接続すると"pong"が返ってきます。/ps(post)にして{"name":"someone"}にすると、"someone"メッセージが返ってきます。エラーのときは、"error"が返ってきます。

main.go
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()
}

テストしよう

公式通りのテストです。

テスト1
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でした。

テスト2
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にあるものとほとんど同じ

テスト3
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についての調査メモ

14
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
6