package service import ( "context" "io" "net/http" "strings" "testing" "cmautobuy/admin/model" ) type staticAIResponseDoer struct { status int body string seen *http.Request } func (d *staticAIResponseDoer) Do(request *http.Request) (*http.Response, error) { d.seen = request return &http.Response{StatusCode: d.status, Body: io.NopCloser(strings.NewReader(d.body))}, nil } func TestOpenAICompatibleModelClient_解析严格JSON且不把密钥放进正文(t *testing.T) { doer := &staticAIResponseDoer{status: 200, body: `{"choices":[{"message":{"content":"{\"conclusion\":\"match\",\"candidate_id\":\"C01\",\"confidence_bps\":9300,\"reason\":\"规格一致\",\"conflict_dimensions\":[],\"missing_dimensions\":[]}"}}]}`} client := NewOpenAICompatibleModelClient(doer) const fakeSecret = "fake-secret-not-production" result, err := client.Match(context.Background(), model.AIProviderConfig{BaseURL: "https://api.example.com/v1", Model: "fake"}, fakeSecret, AIModelMatchRequest{ProductTitle: "测试商品", SourceSpec: "黑色,M", Candidates: []AIModelCandidate{{ID: "C01", Label: "黑色/M"}}}) if err != nil || result.CandidateID != "C01" || result.ConfidenceBPS != 9300 { t.Fatalf("解析结果=%+v err=%v", result, err) } body, _ := io.ReadAll(doer.seen.Body) if strings.Contains(string(body), fakeSecret) { t.Fatal("API Key 只能放 Authorization,不能进入请求正文") } if got := doer.seen.Header.Get("Authorization"); got != "Bearer "+fakeSecret { t.Fatalf("Authorization=%q", got) } } func TestOpenAICompatibleModelClient_拒绝无效或多余模型字段(t *testing.T) { for _, content := range []string{ `not-json`, `{"conclusion":"match","candidate_id":"C01","confidence_bps":9000,"reason":"x","conflict_dimensions":[],"missing_dimensions":[],"option_key":"forged"}`, } { doer := &staticAIResponseDoer{status: 200, body: `{"choices":[{"message":{"content":` + quoteJSONString(content) + `}}]}`} client := NewOpenAICompatibleModelClient(doer) if _, err := client.Match(context.Background(), model.AIProviderConfig{BaseURL: "https://api.example.com/v1", Model: "fake"}, "fake-secret", AIModelMatchRequest{Candidates: []AIModelCandidate{{ID: "C01"}}}); err == nil { t.Fatalf("无效结论应被拒绝: %s", content) } } } func quoteJSONString(value string) string { value = strings.ReplaceAll(value, `\`, `\\`) value = strings.ReplaceAll(value, `"`, `\"`) return `"` + value + `"` }