package middleware import ( "errors" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest/observer" ) func TestErrorHandler_StackTrace(t *testing.T) { // Setup Logger Observer core, logs := observer.New(zapcore.ErrorLevel) logger := zap.New(core) tests := []struct { name string includeStackTrace bool expectStack bool }{ { name: "IncludeStackTrace_True", includeStackTrace: true, expectStack: true, }, { name: "IncludeStackTrace_False", includeStackTrace: false, expectStack: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { logs.TakeAll() // Clear logs gin.SetMode(gin.TestMode) r := gin.New() r.Use(ErrorHandler(logger, nil, tt.includeStackTrace)) r.GET("/error", func(c *gin.Context) { c.Error(errors.New("generic error")) }) req, _ := http.NewRequest("GET", "/error", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) assert.Equal(t, http.StatusInternalServerError, w.Code) // Check logs entries := logs.All() assert.NotEmpty(t, entries, "Should have logged an error") entry := entries[0] fields := entry.ContextMap() _, hasStack := fields["stack_trace"] if tt.expectStack { assert.True(t, hasStack, "Log should contain stack_trace") } else { assert.False(t, hasStack, "Log should NOT contain stack_trace") } }) } }