İçeriğe geç

Test

Gin için test senaryosu nasıl yazılır?

net/http/httptest paketi, HTTP testi için tercih edilen yöntemdir.

Hata ayıklama çıktısını bastırma

Testlerinizde yönlendiriciyi oluşturmadan önce gin.SetMode(gin.TestMode) çağrısı yapın. Bu, Gin’in varsayılan olarak yazdırdığı hata ayıklama düzeyindeki rota kayıt loglarını bastırarak test çıktınızı temiz tutar. Bunu TestMain’e yerleştirerek paketteki tüm testlere uygulanmasını sağlayabilirsiniz:

func TestMain(m *testing.M) {
gin.SetMode(gin.TestMode)
os.Exit(m.Run())
}

Örnek uygulama

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")
}

Temel testler

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/add
func 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())
}

Tablo tabanlı testler

Tablo tabanlı testler, test mantığını tekrarlamadan birçok girdi/çıktı kombinasyonunu kapsamanızı sağlar. Bu kalıp, deyimsel Go’dur ve Gin ile iyi çalışır:

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())
}
})
}
}

Ara katman testi

Bir ara katmanı izole olarak test etmek için, ara katmanın uygulandığı minimal bir yönlendirici ve sonucu kaydeden basit bir işleyici oluşturun:

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)
}