148 lines
4.5 KiB
Go
148 lines
4.5 KiB
Go
package push
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// fakeServer 接收推送请求并保存;返回 status 由调用方控制。
|
|
type fakeServer struct {
|
|
mu sync.Mutex
|
|
requests []Payload
|
|
status int
|
|
}
|
|
|
|
func (f *fakeServer) handler() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
body, _ := io.ReadAll(r.Body)
|
|
_ = r.Body.Close()
|
|
var p Payload
|
|
_ = json.Unmarshal(body, &p)
|
|
f.mu.Lock()
|
|
f.requests = append(f.requests, p)
|
|
status := f.status
|
|
f.mu.Unlock()
|
|
w.WriteHeader(status)
|
|
_, _ = w.Write([]byte(`{"errcode":0}`))
|
|
}
|
|
}
|
|
|
|
func (f *fakeServer) last() Payload {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
if len(f.requests) == 0 {
|
|
return Payload{}
|
|
}
|
|
return f.requests[len(f.requests)-1]
|
|
}
|
|
|
|
func (f *fakeServer) count() int {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
return len(f.requests)
|
|
}
|
|
|
|
// TestUniPushClient_SendHappy 验证:成功路径下请求体含正确字段。
|
|
func TestUniPushClient_SendHappy(t *testing.T) {
|
|
srv := &fakeServer{status: http.StatusOK}
|
|
ts := httptest.NewServer(srv.handler())
|
|
defer ts.Close()
|
|
|
|
c := NewUniPushClient(ts.URL, 2*time.Second, nil)
|
|
err := c.Send(context.Background(), Payload{
|
|
CIDs: []string{"cid-a", "cid-b"},
|
|
Title: "你好",
|
|
Content: "有新消息",
|
|
Data: map[string]interface{}{"notification_id": int64(42), "type": "like"},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 1, srv.count())
|
|
|
|
got := srv.last()
|
|
assert.ElementsMatch(t, []string{"cid-a", "cid-b"}, got.CIDs)
|
|
assert.Equal(t, "你好", got.Title)
|
|
assert.Equal(t, "有新消息", got.Content)
|
|
assert.NotEmpty(t, got.RequestID, "request_id 应自动生成")
|
|
assert.EqualValues(t, 42, got.Data["notification_id"])
|
|
assert.Equal(t, "like", got.Data["type"])
|
|
}
|
|
|
|
// TestUniPushClient_SendNonSuccess 验证:非 2xx 返回 error。
|
|
func TestUniPushClient_SendNonSuccess(t *testing.T) {
|
|
srv := &fakeServer{status: http.StatusBadRequest}
|
|
ts := httptest.NewServer(srv.handler())
|
|
defer ts.Close()
|
|
|
|
c := NewUniPushClient(ts.URL, 2*time.Second, nil)
|
|
err := c.Send(context.Background(), Payload{
|
|
CIDs: []string{"cid-a"}, Title: "x", Content: "y",
|
|
})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "status=400")
|
|
}
|
|
|
|
// TestUniPushClient_EmptyCIDs 验证:cids 为空直接跳过(不发送 HTTP 请求)。
|
|
func TestUniPushClient_EmptyCIDs(t *testing.T) {
|
|
srv := &fakeServer{status: http.StatusOK}
|
|
ts := httptest.NewServer(srv.handler())
|
|
defer ts.Close()
|
|
|
|
c := NewUniPushClient(ts.URL, 2*time.Second, nil)
|
|
err := c.Send(context.Background(), Payload{Title: "x", Content: "y"})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 0, srv.count(), "cids 为空时不应发请求")
|
|
}
|
|
|
|
// TestUniPushClient_EmptyURL 验证:URL 为空时返回 error。
|
|
func TestUniPushClient_EmptyURL(t *testing.T) {
|
|
c := NewUniPushClient("", 2*time.Second, nil)
|
|
err := c.Send(context.Background(), Payload{CIDs: []string{"cid-a"}, Title: "x", Content: "y"})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not initialized")
|
|
}
|
|
|
|
// TestUniPushClient_Timeout 验证:超时场景下返回 error。
|
|
func TestUniPushClient_Timeout(t *testing.T) {
|
|
slow := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
time.Sleep(300 * time.Millisecond)
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer slow.Close()
|
|
|
|
c := NewUniPushClient(slow.URL, 50*time.Millisecond, nil)
|
|
err := c.Send(context.Background(), Payload{CIDs: []string{"cid-a"}, Title: "x", Content: "y"})
|
|
require.Error(t, err)
|
|
assert.True(t, strings.Contains(err.Error(), "timeout") ||
|
|
strings.Contains(err.Error(), "context deadline") ||
|
|
strings.Contains(err.Error(), "Client.Timeout"),
|
|
"expected timeout error, got: %v", err)
|
|
}
|
|
|
|
// TestUniPushClient_RequestIDGenerated 验证:未传 request_id 时自动生成。
|
|
func TestUniPushClient_RequestIDGenerated(t *testing.T) {
|
|
srv := &fakeServer{status: http.StatusOK}
|
|
ts := httptest.NewServer(srv.handler())
|
|
defer ts.Close()
|
|
|
|
c := NewUniPushClient(ts.URL, 2*time.Second, nil)
|
|
_ = c.Send(context.Background(), Payload{CIDs: []string{"x"}, Title: "t", Content: "c"})
|
|
got := srv.last()
|
|
assert.True(t, strings.HasPrefix(got.RequestID, ""), "request_id 应存在")
|
|
assert.Greater(t, len(got.RequestID), 5)
|
|
}
|
|
|
|
// TestNoopPusher 验证:NoopPusher.Send 不报错也不发请求。
|
|
func TestNoopPusher(t *testing.T) {
|
|
var p Pusher = NoopPusher{}
|
|
assert.NoError(t, p.Send(context.Background(), Payload{CIDs: []string{"x"}}))
|
|
} |