Files
go-caatsm/internal/infra/nats/consumer_jetstream_test.go
T

118 lines
3.4 KiB
Go

package nats
import (
"context"
"errors"
"time"
configpkg "caatsm/internal/infra/config"
"github.com/nats-io/nats.go"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"go.uber.org/zap/zaptest"
)
var _ = Describe("Consumer JetStream", func() {
var (
c *Consumer
)
BeforeEach(func() {
logger := zaptest.NewLogger(GinkgoT())
c = &Consumer{
mode: "jetstream",
streamName: "TEST_STREAM",
consumerName: "test-consumer",
subject: "test.subject",
batchSize: 10,
batchTimeout: 2 * time.Second,
logger: logger,
errorHandler: NewErrorHandler(logger),
cfg: &configpkg.Config{
NATS: configpkg.NATSConfig{
ConsumerRules: configpkg.ConsumerRulesConfig{
Backoff: []time.Duration{5 * time.Second, 30 * time.Second},
},
},
},
}
})
Describe("nakWithStrategy", func() {
PIt("sends NAK without delay when backoff is empty", func() {
c.cfg.NATS.ConsumerRules.Backoff = []time.Duration{}
// Note: This test would require a real NATS message to fully test
// For now, we verify the logic path
})
PIt("sends NAK with delay based on delivery attempt", func() {
// Note: This test would require a real NATS message with metadata
// For now, we verify the function exists and can be called
})
})
Describe("handleFetchError", func() {
var ctx context.Context
BeforeEach(func() {
ctx = context.Background()
})
It("returns true for timeout errors", func() {
var sub *nats.Subscription
fetchErrorStreak := 0
shouldContinue, err := c.handleFetchError(ctx, nats.ErrTimeout, &sub, &fetchErrorStreak)
Expect(shouldContinue).To(BeTrue())
Expect(err).NotTo(HaveOccurred())
})
It("handles ErrNoResponders with backoff", func() {
var sub *nats.Subscription
fetchErrorStreak := 0
shouldContinue, err := c.handleFetchError(ctx, nats.ErrNoResponders, &sub, &fetchErrorStreak)
Expect(shouldContinue).To(BeTrue())
Expect(err).NotTo(HaveOccurred())
Expect(fetchErrorStreak).To(Equal(1))
})
It("handles resource not found errors", func() {
var sub *nats.Subscription
fetchErrorStreak := 0
resourceErr := errors.New("stream not found")
shouldContinue, err := c.handleFetchError(ctx, resourceErr, &sub, &fetchErrorStreak)
// Behavior depends on environment; in test this should attempt recovery
Expect(err).To(HaveOccurred())
Expect(shouldContinue).To(BeFalse())
})
It("handles generic errors with backoff", func() {
var sub *nats.Subscription
fetchErrorStreak := 0
genericErr := errors.New("generic error")
shouldContinue, err := c.handleFetchError(ctx, genericErr, &sub, &fetchErrorStreak)
Expect(shouldContinue).To(BeTrue())
Expect(err).NotTo(HaveOccurred())
Expect(fetchErrorStreak).To(Equal(1))
})
})
Describe("buildConsumerConfig", func() {
It("builds consumer config with correct defaults", func() {
config := c.buildConsumerConfig()
Expect(config.Durable).To(Equal("test-consumer"))
Expect(config.AckPolicy).To(Equal(nats.AckExplicitPolicy))
Expect(config.FilterSubject).To(Equal("test.subject"))
})
})
Describe("processSingleMessage", func() {
It("handles successful message processing", func() {
// This would require mocking the processor, but we can test the structure
// For now, we verify the method exists and can be called
// Note: This test would need a mock processor to fully work
Skip("Requires mock message processor")
})
})
})