package wechat import ( "context" "net/http" "net/http/httptest" "testing" ) // PullToken 正常路径:带对密钥、解析 token + 有效期。 func TestPullToken_OK(t *testing.T) { var gotAuth string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotAuth = r.Header.Get("Authorization") w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"access_token":"TOKEN_ABC","expires_in":7200}`)) })) defer srv.Close() tok, ttl, err := PullToken(context.Background(), srv.URL, "s3cr3t") if err != nil { t.Fatal(err) } if tok != "TOKEN_ABC" || ttl != 7200 { t.Fatalf("解析错:tok=%q ttl=%d", tok, ttl) } if gotAuth != "Bearer s3cr3t" { t.Fatalf("密钥头没带对:%q", gotAuth) } } // 中控拒绝(密钥不对 → 403)必须报错,不能把 403 页面当 token。 func TestPullToken_Rejected(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusForbidden) _, _ = w.Write([]byte("forbidden")) })) defer srv.Close() if _, _, err := PullToken(context.Background(), srv.URL, "wrong"); err == nil { t.Fatal("403 应报错") } } // 坏 JSON / 空 token 必须报错,不能返回空串当成功。 func TestPullToken_BadBody(t *testing.T) { for _, body := range []string{`not json`, `{"access_token":""}`, `{}`} { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(body)) })) if _, _, err := PullToken(context.Background(), srv.URL, ""); err == nil { t.Fatalf("坏响应 %q 应报错", body) } srv.Close() } } // 中控没给 expires_in 时按微信默认 7200 兜底(避免缓存 0 秒后每次都拉)。 func TestPullToken_DefaultExpiry(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(`{"access_token":"X"}`)) })) defer srv.Close() _, ttl, err := PullToken(context.Background(), srv.URL, "") if err != nil || ttl != 7200 { t.Fatalf("应兜底 7200,得 ttl=%d err=%v", ttl, err) } }