package middleware import ( "context" "net/http" "net/http/httptest" "strings" "testing" "time" "kra/internal/biz" "kra/internal/service" "github.com/gin-gonic/gin" ) type rateLimitSecurityRepo struct{} func (rateLimitSecurityRepo) SecurityConfig(context.Context) (*biz.SecurityConfig, error) { return &biz.SecurityConfig{LimitEnable: true, LimitWindow: 60, LimitCount: 1}, nil } func (rateLimitSecurityRepo) SaveSecurityConfig(context.Context, *biz.SecurityConfig) error { return nil } type rateLimitCache struct{} func (rateLimitCache) Get(context.Context, string) (string, bool, error) { return "", false, nil } func (rateLimitCache) Set(context.Context, string, string, time.Duration) error { return nil } func (rateLimitCache) Delete(context.Context, string) error { return nil } func (rateLimitCache) Increment(context.Context, string, time.Duration) (int64, error) { return 2, nil } func TestSecurityRateLimitMatchesResponseContract(t *testing.T) { gin.SetMode(gin.TestMode) settings := service.NewSecurityService(biz.NewSecurityUsecase(rateLimitSecurityRepo{}, rateLimitCache{}, nil, nil)) engine := gin.New() engine.Use(SecurityRateLimit(settings)) engine.POST("/base/login", func(c *gin.Context) { c.Status(http.StatusNoContent) }) response := httptest.NewRecorder() engine.ServeHTTP(response, httptest.NewRequest(http.MethodPost, "/base/login", nil)) if response.Code != http.StatusOK { t.Fatalf("status = %d, body=%s", response.Code, response.Body.String()) } body := response.Body.String() if !strings.Contains(body, `"code":7`) || !strings.Contains(body, `"msg":"请求太过频繁,请稍后再试"`) || strings.Contains(body, `"data"`) { t.Fatalf("unexpected rate-limit response: %s", body) } }