veza/veza-backend-api/internal/middleware/request_id_test.go
2025-12-03 20:29:37 +01:00

192 lines
5.8 KiB
Go

package middleware
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRequestID_GeneratesUUID(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(RequestID())
router.GET("/test", func(c *gin.Context) {
requestID, exists := c.Get("request_id")
require.True(t, exists, "request_id should be set in context")
c.JSON(http.StatusOK, gin.H{"request_id": requestID})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
// Vérifier que le header X-Request-ID est présent
headerValue := w.Header().Get("X-Request-ID")
assert.NotEmpty(t, headerValue, "X-Request-ID header should be present")
// Vérifier que c'est un UUID valide
_, err := uuid.Parse(headerValue)
assert.NoError(t, err, "X-Request-ID should be a valid UUID")
// Vérifier que le request ID est dans la réponse JSON
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
require.NoError(t, err)
responseRequestID, ok := response["request_id"].(string)
require.True(t, ok, "request_id should be a string in response")
assert.Equal(t, headerValue, responseRequestID, "request_id in response should match header")
}
func TestRequestID_UsesExistingHeader(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(RequestID())
customRequestID := "custom-request-id-12345"
router.GET("/test", func(c *gin.Context) {
requestID, exists := c.Get("request_id")
require.True(t, exists, "request_id should be set in context")
c.JSON(http.StatusOK, gin.H{"request_id": requestID})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
req.Header.Set("X-Request-ID", customRequestID)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
// Vérifier que le header X-Request-ID utilise la valeur fournie
headerValue := w.Header().Get("X-Request-ID")
assert.Equal(t, customRequestID, headerValue, "X-Request-ID should use provided header value")
// Vérifier que le request ID est dans la réponse JSON
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
require.NoError(t, err)
responseRequestID, ok := response["request_id"].(string)
require.True(t, ok, "request_id should be a string in response")
assert.Equal(t, customRequestID, responseRequestID, "request_id in response should match provided header")
}
func TestRequestID_UniquePerRequest(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(RequestID())
router.GET("/test", func(c *gin.Context) {
requestID, _ := c.Get("request_id")
c.JSON(http.StatusOK, gin.H{"request_id": requestID})
})
// Faire plusieurs requêtes et vérifier qu'elles ont des IDs différents
requestIDs := make(map[string]bool)
for i := 0; i < 10; i++ {
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
require.NoError(t, err)
requestID, ok := response["request_id"].(string)
require.True(t, ok, "request_id should be a string")
// Vérifier que chaque ID est unique
assert.False(t, requestIDs[requestID], "Each request should have a unique ID")
requestIDs[requestID] = true
}
}
func TestRequestID_EmptyHeaderGeneratesNew(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(RequestID())
router.GET("/test", func(c *gin.Context) {
requestID, _ := c.Get("request_id")
c.JSON(http.StatusOK, gin.H{"request_id": requestID})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
// Ne pas définir de header X-Request-ID
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
headerValue := w.Header().Get("X-Request-ID")
assert.NotEmpty(t, headerValue, "X-Request-ID should be generated even if not provided")
// Vérifier que c'est un UUID valide
_, err := uuid.Parse(headerValue)
assert.NoError(t, err, "Generated X-Request-ID should be a valid UUID")
}
func TestRequestID_AvailableInLogger(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(RequestID())
var capturedRequestID string
router.GET("/test", func(c *gin.Context) {
// Simuler l'utilisation dans un logger
if requestID, exists := c.Get("request_id"); exists {
capturedRequestID = requestID.(string)
}
c.JSON(http.StatusOK, gin.H{"ok": true})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
assert.NotEmpty(t, capturedRequestID, "request_id should be available for logger")
// Vérifier que le request ID capturé correspond au header
headerValue := w.Header().Get("X-Request-ID")
assert.Equal(t, headerValue, capturedRequestID, "captured request_id should match header")
}
func TestRequestID_MultipleRequests(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(RequestID())
// Utiliser router.Any() pour accepter toutes les méthodes HTTP testées
router.Any("/test", func(c *gin.Context) {
requestID, _ := c.Get("request_id")
c.JSON(http.StatusOK, gin.H{"request_id": requestID})
})
// Tester avec différentes méthodes HTTP
methods := []string{"GET", "POST", "PUT", "DELETE"}
for _, method := range methods {
w := httptest.NewRecorder()
req := httptest.NewRequest(method, "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code, "Request with method %s should return 200", method)
headerValue := w.Header().Get("X-Request-ID")
assert.NotEmpty(t, headerValue, "X-Request-ID should be present for %s requests", method)
}
}