2026-04-30 02:30:32 +08:00

88 lines
2.5 KiB
Go

// Package mysqltest provides real room-service MySQL repositories for tests.
package mysqltest
import (
"context"
"database/sql"
"testing"
"google.golang.org/protobuf/proto"
roomeventsv1 "hyapp/api/proto/events/room/v1"
"hyapp/internal/testutil/mysqlschema"
"hyapp/services/room-service/internal/room/outbox"
mysqlstorage "hyapp/services/room-service/internal/storage/mysql"
)
// Repository wraps the production room MySQL repository with test-only read helpers.
type Repository struct {
*mysqlstorage.Repository
t testing.TB
schema *mysqlschema.Schema
}
// NewRepository creates an isolated room schema and opens the production repository.
func NewRepository(t testing.TB) *Repository {
t.Helper()
schema := mysqlschema.New(t, mysqlschema.Config{
EnvVar: "ROOM_SERVICE_MYSQL_TEST_DSN",
InitDBPath: initDBPath(t),
DatabasePrefix: "hyapp_room_test",
})
repository, err := mysqlstorage.Open(context.Background(), schema.DSN, 4, 4)
if err != nil {
t.Fatalf("open room mysql repository failed: %v", err)
}
wrapped := &Repository{Repository: repository, t: t, schema: schema}
t.Cleanup(wrapped.Close)
return wrapped
}
// Close shuts down the repository; mysqlschema owns schema cleanup.
func (r *Repository) Close() {
r.t.Helper()
if r.Repository != nil {
_ = r.Repository.Close()
}
}
// OutboxRecord reads one outbox row, including published rows that normal scans skip.
func (r *Repository) OutboxRecord(eventID string) (outbox.Record, bool) {
r.t.Helper()
row := r.schema.DB.QueryRowContext(context.Background(), `
SELECT event_id, event_type, room_id, status, envelope, created_at, retry_count, COALESCE(last_error, '')
FROM room_outbox
WHERE event_id = ?
`, eventID)
var envelopeBytes []byte
var record outbox.Record
if err := row.Scan(&record.EventID, &record.EventType, &record.RoomID, &record.Status, &envelopeBytes, &record.CreatedAt, &record.RetryCount, &record.LastError); err != nil {
if err == sql.ErrNoRows {
return outbox.Record{}, false
}
r.t.Fatalf("query room outbox record failed: %v", err)
}
var envelope roomeventsv1.EventEnvelope
if err := proto.Unmarshal(envelopeBytes, &envelope); err != nil {
r.t.Fatalf("decode room outbox envelope failed: %v", err)
}
record.Envelope = &envelope
return record, true
}
func initDBPath(t testing.TB) string {
t.Helper()
return mysqlschema.InitDBPath(t,
mysqlschema.CallerFile(t, 1),
"..", "..", "..", "deploy", "mysql", "initdb", "001_room_service.sql",
)
}