117 lines
3.5 KiB
Go
117 lines
3.5 KiB
Go
|
|
package testkit
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"apps/backend/internal/config"
|
||
|
|
"apps/backend/internal/domain"
|
||
|
|
"apps/backend/internal/handler"
|
||
|
|
"apps/backend/internal/response"
|
||
|
|
"apps/backend/internal/svc"
|
||
|
|
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
"github.com/zeromicro/go-zero/core/stores/cache"
|
||
|
|
"github.com/zeromicro/go-zero/core/stores/redis"
|
||
|
|
"github.com/zeromicro/go-zero/rest"
|
||
|
|
)
|
||
|
|
|
||
|
|
// FixedNow is a frozen clock for schedule tests (M4+).
|
||
|
|
var FixedNow = time.Date(2026, 7, 10, 12, 0, 0, 0, time.UTC)
|
||
|
|
|
||
|
|
// TestConfig returns a minimal in-memory config for tests.
|
||
|
|
func TestConfig() config.Config {
|
||
|
|
var c config.Config
|
||
|
|
c.Name = "haixun-test"
|
||
|
|
c.Host = "127.0.0.1"
|
||
|
|
c.Port = 0
|
||
|
|
c.Timeout = 3000
|
||
|
|
c.Log.Mode = "console"
|
||
|
|
c.Log.Level = "error"
|
||
|
|
c.Mongo.URI = "mongodb://127.0.0.1:27017"
|
||
|
|
c.Mongo.Database = "haixun_test"
|
||
|
|
c.CacheRedis = cache.CacheConf{{
|
||
|
|
RedisConf: redis.RedisConf{Host: "127.0.0.1:6379", Type: "node"},
|
||
|
|
Weight: 100,
|
||
|
|
}}
|
||
|
|
c.Auth.AccessSecret = "test-access"
|
||
|
|
c.Auth.RefreshSecret = "test-refresh"
|
||
|
|
c.Auth.AccessExpire = 3600
|
||
|
|
c.Auth.RefreshExpire = 86400
|
||
|
|
c.Worker.ID = "test-worker"
|
||
|
|
c.Worker.PollIntervalMs = 100
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// StartGateway builds a rest.Server with registered routes (not listening).
|
||
|
|
// Callers use ServeHTTP via httptest for unit/integration without bind.
|
||
|
|
func StartGateway(t *testing.T) (*rest.Server, *svc.ServiceContext) {
|
||
|
|
t.Helper()
|
||
|
|
c := TestConfig()
|
||
|
|
// Avoid log spam / file mode issues in tests
|
||
|
|
server := rest.MustNewServer(c.RestConf)
|
||
|
|
ctx := svc.NewServiceContext(c)
|
||
|
|
handler.RegisterHandlers(server, ctx)
|
||
|
|
t.Cleanup(func() { server.Stop() })
|
||
|
|
return server, ctx
|
||
|
|
}
|
||
|
|
|
||
|
|
// AssertEnvelope102000 checks success envelope shape (A-07).
|
||
|
|
func AssertEnvelope102000(t *testing.T, body []byte) response.Envelope {
|
||
|
|
t.Helper()
|
||
|
|
var env response.Envelope
|
||
|
|
require.NoError(t, json.Unmarshal(body, &env))
|
||
|
|
require.Equal(t, domain.SuccessCode, env.Code, "expected success code 102000")
|
||
|
|
require.NotEmpty(t, env.Message)
|
||
|
|
require.Nil(t, env.Error)
|
||
|
|
return env
|
||
|
|
}
|
||
|
|
|
||
|
|
// AssertFailNotEmptySuccess ensures response is not 102000 with empty success (X-01).
|
||
|
|
func AssertFailNotEmptySuccess(t *testing.T, body []byte) response.Envelope {
|
||
|
|
t.Helper()
|
||
|
|
var env response.Envelope
|
||
|
|
require.NoError(t, json.Unmarshal(body, &env))
|
||
|
|
require.NotEqual(t, domain.SuccessCode, env.Code, "must not be success empty")
|
||
|
|
require.NotEmpty(t, env.Message)
|
||
|
|
return env
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetJSON issues GET against the in-process server mux via handler registration.
|
||
|
|
// go-zero rest.Server does not expose ServeHTTP easily in all versions; we re-register
|
||
|
|
// on a plain mux for tests.
|
||
|
|
func NewTestMux(svcCtx *svc.ServiceContext) http.Handler {
|
||
|
|
mux := http.NewServeMux()
|
||
|
|
// Mirror routes.go paths for testkit convenience
|
||
|
|
h := handlerProbe{svc: svcCtx}
|
||
|
|
mux.HandleFunc("GET /api/v1/ping", h.ping)
|
||
|
|
mux.HandleFunc("GET /api/v1/health", h.ping)
|
||
|
|
mux.HandleFunc("GET /api/v1/_not_implemented_probe", h.notImpl)
|
||
|
|
return mux
|
||
|
|
}
|
||
|
|
|
||
|
|
type handlerProbe struct {
|
||
|
|
svc *svc.ServiceContext
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h handlerProbe) ping(w http.ResponseWriter, r *http.Request) {
|
||
|
|
// Import cycle avoided: call response directly with same payload as ping logic
|
||
|
|
response.OK(w, map[string]string{"status": "ok", "service": "haixun-gateway"})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h handlerProbe) notImpl(w http.ResponseWriter, r *http.Request) {
|
||
|
|
response.NotImplemented(w, "probe")
|
||
|
|
}
|
||
|
|
|
||
|
|
// DoGet helper
|
||
|
|
func DoGet(t *testing.T, h http.Handler, path string) *httptest.ResponseRecorder {
|
||
|
|
t.Helper()
|
||
|
|
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||
|
|
rr := httptest.NewRecorder()
|
||
|
|
h.ServeHTTP(rr, req)
|
||
|
|
return rr
|
||
|
|
}
|