package usecase import ( "context" "testing" "apps/backend/internal/module/ai" "apps/backend/internal/module/radar/domain" ) func TestJudgeCacheAvoidsSecondProviderCall(t *testing.T) { client := &countingJudgeAI{} svc := New(nil) svc.AI = client cand := &domain.CandidatePost{ExternalID: "https://threads.net/@a/post/1", Text: "有人推薦保母嗎", Classification: "seeking_recommendation"} first, firstCredits, err := svc.JudgeCandidate(context.Background(), 42, nil, nil, cand) if err != nil { t.Fatal(err) } second, secondCredits, err := svc.JudgeCandidate(context.Background(), 42, nil, nil, cand) if err != nil { t.Fatal(err) } if client.calls != 1 || first == nil || second == nil || firstCredits == 0 || secondCredits != 0 { t.Fatalf("cache/provider accounting mismatch: calls=%d first=%d second=%d", client.calls, firstCredits, secondCredits) } } type countingJudgeAI struct{ calls int } func (c *countingJudgeAI) Complete(context.Context, string, string, string) (string, error) { c.calls++ return `{"status":"qualified","intent_score":80,"region_match":"unknown","reasons":[{"dimension":"authenticity","score":30,"reason":"真實求助"},{"dimension":"intent","score":30,"reason":"明確求推薦"},{"dimension":"region","score":15,"reason":"未提供地區"},{"dimension":"freshness","score":15,"reason":"近期貼文"},{"dimension":"fit","score":10,"reason":"命中需求"}]}`, nil } func (c *countingJudgeAI) CompleteStream(context.Context, string, string, string, func(string) error) (string, error) { c.calls++ return `{"status":"qualified","intent_score":80,"region_match":"unknown","reasons":[{"dimension":"authenticity","score":30,"reason":"真實求助"},{"dimension":"intent","score":30,"reason":"明確求推薦"},{"dimension":"region","score":15,"reason":"未提供地區"},{"dimension":"freshness","score":15,"reason":"近期貼文"},{"dimension":"fit","score":10,"reason":"命中需求"}]}`, nil } func (c *countingJudgeAI) ListModels(context.Context, string) ([]string, error) { return []string{"test"}, nil } var _ ai.Client = (*countingJudgeAI)(nil)