Testing Package Reference
Complete reference for github.com/zoobz-io/capitan/testing. For usage patterns and testing strategies, see the Testing Guide.
import capitantesting "github.com/zoobz-io/capitan/testing"
EventCapture
Captures events for testing and verification.
NewEventCapture
func NewEventCapture() *EventCapture
Creates a new capture instance.
Handler
func (ec *EventCapture) Handler() capitan.EventCallback
Returns a callback for use with Hook or Observe.
Events
func (ec *EventCapture) Events() []CapturedEvent
Returns all captured events as a defensive copy.
Count
func (ec *EventCapture) Count() int
Returns the number of captured events.
Reset
func (ec *EventCapture) Reset()
Clears all captured events.
WaitForCount
func (ec *EventCapture) WaitForCount(n int, timeout time.Duration) bool
Blocks until the capture has at least n events or timeout expires. Returns true if count was reached.
CapturedEvent
Snapshot of captured event data:
type CapturedEvent struct {
Signal capitan.Signal
Timestamp time.Time
Severity capitan.Severity
Fields []capitan.Field
}
Example
func TestEmission(t *testing.T) {
c := capitan.New(capitan.WithSyncMode())
defer c.Shutdown()
capture := capitantesting.NewEventCapture()
c.Hook(orderCreated, capture.Handler())
c.Emit(context.Background(), orderCreated, orderID.Field("ORD-123"))
events := capture.Events()
if len(events) != 1 {
t.Fatalf("expected 1 event, got %d", len(events))
}
id := orderID.ExtractFromFields(events[0].Fields)
if id != "ORD-123" {
t.Errorf("expected ORD-123, got %s", id)
}
}
EventCounter
Counts events without storing them.
NewEventCounter
func NewEventCounter() *EventCounter
Creates a new counter instance.
Handler
func (ec *EventCounter) Handler() capitan.EventCallback
Returns a callback for use with Hook or Observe.
Count
func (ec *EventCounter) Count() int64
Returns the current count.
Reset
func (ec *EventCounter) Reset()
Resets the count to zero.
WaitForCount
func (ec *EventCounter) WaitForCount(n int64, timeout time.Duration) bool
Blocks until count reaches n or timeout expires. Returns true if count was reached.
Example
func TestBulkEmission(t *testing.T) {
c := capitan.New(capitan.WithSyncMode())
defer c.Shutdown()
counter := capitantesting.NewEventCounter()
c.Hook(signal, counter.Handler())
for i := 0; i < 1000; i++ {
c.Emit(context.Background(), signal)
}
if counter.Count() != 1000 {
t.Errorf("expected 1000, got %d", counter.Count())
}
}
PanicRecorder
Records panics from listeners.
NewPanicRecorder
func NewPanicRecorder() *PanicRecorder
Creates a new recorder instance.
Handler
func (pr *PanicRecorder) Handler() func(capitan.Signal, any)
Returns a panic handler for use with WithPanicHandler.
Panics
func (pr *PanicRecorder) Panics() []PanicRecord
Returns all recorded panics as a defensive copy.
Count
func (pr *PanicRecorder) Count() int
Returns the number of recorded panics.
Reset
func (pr *PanicRecorder) Reset()
Clears all recorded panics.
PanicRecord
type PanicRecord struct {
Signal capitan.Signal
Recovered any
Timestamp time.Time
}
Example
func TestPanicRecovery(t *testing.T) {
recorder := capitantesting.NewPanicRecorder()
c := capitan.New(
capitan.WithSyncMode(),
capitan.WithPanicHandler(recorder.Handler()),
)
defer c.Shutdown()
c.Hook(signal, func(ctx context.Context, e *capitan.Event) {
panic("test panic")
})
c.Emit(context.Background(), signal)
panics := recorder.Panics()
if len(panics) != 1 {
t.Fatalf("expected 1 panic, got %d", len(panics))
}
if panics[0].Recovered != "test panic" {
t.Errorf("wrong panic value: %v", panics[0].Recovered)
}
}
StatsWaiter
Polls stats until conditions are met.
NewStatsWaiter
func NewStatsWaiter(c *capitan.Capitan) *StatsWaiter
Creates a waiter for the given instance.
WaitForWorkers
func (sw *StatsWaiter) WaitForWorkers(n int, timeout time.Duration) bool
Blocks until at least n workers are active or timeout expires.
WaitForEmptyQueues
func (sw *StatsWaiter) WaitForEmptyQueues(timeout time.Duration) bool
Blocks until all signal queues are empty or timeout expires.
WaitForEmitCount
func (sw *StatsWaiter) WaitForEmitCount(signal capitan.Signal, n uint64, timeout time.Duration) bool
Blocks until the signal's emit count reaches n or timeout expires.
Example
func TestAsyncProcessing(t *testing.T) {
c := capitan.New() // async mode
defer c.Shutdown()
waiter := capitantesting.NewStatsWaiter(c)
c.Hook(signal, func(ctx context.Context, e *capitan.Event) {})
c.Emit(context.Background(), signal)
if !waiter.WaitForWorkers(1, time.Second) {
t.Fatal("worker not created")
}
if !waiter.WaitForEmptyQueues(time.Second) {
t.Fatal("queue not drained")
}
}
FieldExtractor
Utility for extracting typed values from events.
NewFieldExtractor
func NewFieldExtractor() *FieldExtractor
Creates a new extractor.
GetString
func (fe *FieldExtractor) GetString(e *capitan.Event, key capitan.StringKey) string
Extracts a string value. Returns empty string if missing.
GetInt
func (fe *FieldExtractor) GetInt(e *capitan.Event, key capitan.IntKey) int
Extracts an int value. Returns zero if missing.
GetBool
func (fe *FieldExtractor) GetBool(e *capitan.Event, key capitan.BoolKey) bool
Extracts a bool value. Returns false if missing.
GetFloat64
func (fe *FieldExtractor) GetFloat64(e *capitan.Event, key capitan.Float64Key) float64
Extracts a float64 value. Returns zero if missing.
TestCapitan
TestCapitan
func TestCapitan(opts ...capitan.Option) *capitan.Capitan
Creates an instance for testing. Equivalent to capitan.New(opts...) but communicates test intent.