テスト
Ginのテストケースの書き方
net/http/httptestパッケージはHTTPテストの推奨方法です。
デバッグ出力の抑制
テストでルーターを作成する前にgin.SetMode(gin.TestMode)を呼び出します。これにより、Ginがデフォルトで出力するデバッグレベルのルート登録ログが抑制され、テスト出力がクリーンに保たれます。パッケージ内のすべてのテストに適用するためにTestMainに配置できます:
func TestMain(m *testing.M) { gin.SetMode(gin.TestMode) os.Exit(m.Run())}サンプルアプリケーション
package main
import "github.com/gin-gonic/gin"
type User struct { Username string `json:"username"` Gender string `json:"gender"`}
func setupRouter() *gin.Engine { router := gin.Default() router.GET("/ping", func(c *gin.Context) { c.String(200, "pong") }) return router}
func postUser(router *gin.Engine) *gin.Engine { router.POST("/user/add", func(c *gin.Context) { var user User c.BindJSON(&user) c.JSON(200, user) }) return router}
func main() { router := setupRouter() router = postUser(router) router.Run(":8080")}基本テスト
package main
import ( "net/http" "net/http/httptest" "encoding/json" "testing" "strings"
"github.com/stretchr/testify/assert")
func TestPingRoute(t *testing.T) { router := setupRouter()
w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/ping", nil) router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code) assert.Equal(t, "pong", w.Body.String())}
// Test for POST /user/addfunc TestPostUser(t *testing.T) { router := setupRouter() router = postUser(router)
w := httptest.NewRecorder()
// Create an example user for testing exampleUser := User{ Username: "test_name", Gender: "male", } userJson, _ := json.Marshal(exampleUser) req, _ := http.NewRequest("POST", "/user/add", strings.NewReader(string(userJson))) router.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code) // Compare the response body with the json data of exampleUser assert.Equal(t, string(userJson), w.Body.String())}テーブル駆動テスト
テーブル駆動テストでは、テストロジックを重複させることなく、多くの入出力の組み合わせをカバーできます。このパターンはGoの慣用的な方法で、Ginとうまく連携します:
func TestPingRouteTableDriven(t *testing.T) { router := setupRouter()
tests := []struct { name string method string path string wantCode int wantBody string }{ {"ping endpoint", "GET", "/ping", 200, "pong"}, {"not found", "GET", "/nonexistent", 404, ""}, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := httptest.NewRecorder() req, _ := http.NewRequest(tt.method, tt.path, nil) router.ServeHTTP(w, req)
assert.Equal(t, tt.wantCode, w.Code) if tt.wantBody != "" { assert.Equal(t, tt.wantBody, w.Body.String()) } }) }}ミドルウェアのテスト
ミドルウェアを単独でテストするには、ミドルウェアを適用した最小限のルーターと結果を記録するシンプルなハンドラを作成します:
func TestAuthMiddleware(t *testing.T) { gin.SetMode(gin.TestMode)
// Create a router with the middleware under test router := gin.New() router.Use(AuthRequired()) // your middleware
router.GET("/protected", func(c *gin.Context) { c.String(200, "ok") })
// Test without credentials -- expect 401 w := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/protected", nil) router.ServeHTTP(w, req) assert.Equal(t, 401, w.Code)
// Test with valid credentials -- expect 200 w = httptest.NewRecorder() req, _ = http.NewRequest("GET", "/protected", nil) req.Header.Set("Authorization", "Bearer valid-token") router.ServeHTTP(w, req) assert.Equal(t, 200, w.Code)}