veza/veza-backend-api/internal/middleware/error_handler_metrics_test.go
2025-12-12 21:34:34 -05:00

156 lines
4.6 KiB
Go

package middleware
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"veza-backend-api/internal/errors"
"veza-backend-api/internal/metrics"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)
func TestErrorHandler_RecordsMetrics(t *testing.T) {
gin.SetMode(gin.TestMode)
logger := zap.NewNop()
errorMetrics := metrics.NewErrorMetrics()
router := gin.New()
router.Use(ErrorHandler(logger, errorMetrics, true))
router.GET("/test", func(c *gin.Context) {
c.Error(errors.NewNotFoundError("User"))
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusNotFound, w.Code)
// Vérifier que les métriques ont été enregistrées
stats := errorMetrics.GetStats()
assert.Equal(t, int64(1), stats["total_errors"])
errorsByCode := stats["errors_by_code"].(map[errors.ErrorCode]int64)
assert.Equal(t, int64(1), errorsByCode[errors.ErrCodeNotFound])
errorsByHTTPStatus := stats["errors_by_http_status"].(map[int]int64)
assert.Equal(t, int64(1), errorsByHTTPStatus[404])
}
func TestErrorHandler_RecordsMetricsForValidationError(t *testing.T) {
gin.SetMode(gin.TestMode)
logger := zap.NewNop()
errorMetrics := metrics.NewErrorMetrics()
router := gin.New()
router.Use(ErrorHandler(logger, errorMetrics, true))
router.GET("/test", func(c *gin.Context) {
c.Error(errors.NewValidationError("Invalid input"))
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
stats := errorMetrics.GetStats()
assert.Equal(t, int64(1), stats["total_errors"])
errorsByHTTPStatus := stats["errors_by_http_status"].(map[int]int64)
assert.Equal(t, int64(1), errorsByHTTPStatus[400])
}
func TestErrorHandler_RecordsMetricsForInternalError(t *testing.T) {
gin.SetMode(gin.TestMode)
logger := zap.NewNop()
errorMetrics := metrics.NewErrorMetrics()
router := gin.New()
router.Use(ErrorHandler(logger, errorMetrics, true))
router.GET("/test", func(c *gin.Context) {
c.Error(errors.New(errors.ErrCodeInternal, "Something went wrong"))
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusInternalServerError, w.Code)
stats := errorMetrics.GetStats()
assert.Equal(t, int64(1), stats["total_errors"])
errorsByCode := stats["errors_by_code"].(map[errors.ErrorCode]int64)
assert.Equal(t, int64(1), errorsByCode[errors.ErrCodeInternal])
errorsByHTTPStatus := stats["errors_by_http_status"].(map[int]int64)
assert.Equal(t, int64(1), errorsByHTTPStatus[500])
}
func TestErrorHandler_RecordsMultipleErrors(t *testing.T) {
gin.SetMode(gin.TestMode)
logger := zap.NewNop()
errorMetrics := metrics.NewErrorMetrics()
router := gin.New()
router.Use(ErrorHandler(logger, errorMetrics, true))
router.GET("/notfound", func(c *gin.Context) {
c.Error(errors.NewNotFoundError("Resource"))
})
router.GET("/validation", func(c *gin.Context) {
c.Error(errors.NewValidationError("Invalid"))
})
router.GET("/internal", func(c *gin.Context) {
c.Error(errors.New(errors.ErrCodeInternal, "Error"))
})
// Simuler plusieurs erreurs
httptest.NewRecorder()
req1 := httptest.NewRequest("GET", "/notfound", nil)
w1 := httptest.NewRecorder()
router.ServeHTTP(w1, req1)
req2 := httptest.NewRequest("GET", "/validation", nil)
w2 := httptest.NewRecorder()
router.ServeHTTP(w2, req2)
req3 := httptest.NewRequest("GET", "/internal", nil)
w3 := httptest.NewRecorder()
router.ServeHTTP(w3, req3)
stats := errorMetrics.GetStats()
assert.Equal(t, int64(3), stats["total_errors"])
errorsByHTTPStatus := stats["errors_by_http_status"].(map[int]int64)
assert.Equal(t, int64(1), errorsByHTTPStatus[404])
assert.Equal(t, int64(1), errorsByHTTPStatus[400])
assert.Equal(t, int64(1), errorsByHTTPStatus[500])
}
func TestErrorHandler_WorksWithoutMetrics(t *testing.T) {
gin.SetMode(gin.TestMode)
logger := zap.NewNop()
router := gin.New()
// Passer nil pour les métriques - ne doit pas planter
router.Use(ErrorHandler(logger, nil, true))
router.GET("/test", func(c *gin.Context) {
c.Error(errors.NewNotFoundError("User"))
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/test", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusNotFound, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
require.NoError(t, err)
errorObj := response["error"].(map[string]interface{})
assert.Equal(t, float64(errors.ErrCodeNotFound), errorObj["code"])
}