mock://¶
Producer-only test sink. Every exchange routed to a mock:// endpoint
is recorded; the test then introspects it via Endpoint methods
(ReceivedCount, Received, ExpectedBodiesReceived,
AssertIsSatisfied, …). Supports a full test-sink surface (expectedCount, assertPeriod, retainFirst/retainLast, failFast,
log, resultWaitTime, copyOnExchange, sleepForEmptyTest,
reportGroup) and adds Helix-specific extensions for request-matched
stubs and canned replies.
Use this for unit/integration testing routes. Do not use it in production routes — it is a sink that holds exchanges in memory.
URI shape¶
<name> is a free-form identifier. Endpoints with the same name share
the recorder; re-creation returns the existing endpoint.
Parameters¶
| Param | Type | Default | Description |
|---|---|---|---|
name |
path | — | Endpoint identifier. |
expectedCount |
integer | -1 |
Producer: expected number of messages. -1 = unset. 0 triggers the sleepForEmptyTest confirmation path. |
assertPeriod |
duration | 0 |
Producer: grace period after expectedCount is satisfied. Re-checks to ensure no MORE messages arrived. |
copyOnExchange |
boolean | true |
Producer: deep-copy the incoming exchange before recording (prevents downstream mutation from changing what the assert sees). |
failFast |
boolean | true |
Producer: fail at the first detected mismatch (vs wait for the full count and report everything). |
log |
boolean | false |
Producer: log every incoming message at INFO. |
reportGroup |
integer | 0 |
Producer: log a throughput report every N messages (0 = off). |
resultMinimumWaitTime |
duration | 0 |
Producer: minimum wait before AssertIsSatisfied can return — lets in-flight tail work arrive. |
resultWaitTime |
duration | 5s |
Producer: maximum wait for AssertIsSatisfied(0). |
retainFirst |
integer | -1 |
Producer: keep only the first N exchanges (memory savings). TotalReceivedCount still tracks the real arrival count. |
retainLast |
integer | -1 |
Producer: keep only the last N exchanges. |
sleepForEmptyTest |
duration | 0 |
Producer: when expectedCount=0, sleep this long to confirm no messages arrived. |
Durations accept Go format or integer milliseconds.
Assertion API (Go)¶
The URI params above tune the asserter; the actual assertion calls live
on *mock.Endpoint. Pull the endpoint from the running context
(ctx.ResolveEndpoint(...).(*mock.Endpoint)) and call any combination
of:
ExpectedMessageCount(n)— exact count.SetMinimumExpectedMessageCount(n)— at least N.ExpectedBodiesReceived(b1, b2, …)— bodies in this order.ExpectedBodiesReceivedInAnyOrder(b1, b2, …)— order-insensitive.ExpectedHeaderReceived(name, value)— every exchange has header.ExpectedHeaderValuesReceivedInAnyOrder(name, v1, v2, …)— multi-value match.Expects(func(i, ex) error)— arbitrary per-exchange predicate.ExpectsAscending(expr)/ExpectsDescending(expr)/ExpectsNoDuplicates(expr).WhenAnyExchangeReceived(processor)— run on every arrival.ReturnReplyBody(any)/ReturnReplyHeader(name, value)— canned reply for InOut callers.AddStub(&mock.Stub{...})— request-matched canned response (Helix extension).AssertIsSatisfied(timeout)— wait & validate.
Stubs (Helix extension)¶
mock.Stub registers a request-matched canned response. Multiple stubs
are tried in registration order; the first whose matchers all hit
wins. Fields:
type Stub struct {
// Match — any combination; all set fields must match.
BodyContains string
BodyEquals string
HeaderEquals map[string]string
HeaderContains map[string]string
// Respond.
Body any
Headers map[string]any
Status int // sets HelixHttpResponseCode (useful for http stubs)
Delay time.Duration // simulated latency
Error string // if non-empty, the stub returns an error
}
Body shape¶
Producer-only. Consumers are not supported.
Examples¶
Assert a route sent two messages with specific bodies:
ep := ctx.MustResolveEndpoint("mock://output").(*mock.Endpoint)
ep.ExpectedBodiesReceived("alice", "bob")
// drive the route…
if err := ep.AssertIsSatisfied(0); err != nil {
t.Fatal(err)
}
Cap memory on a long-running soak:
(only first 50 + last 50 are kept; TotalReceivedCount() still
reports the real number.)
Request-matched stub for an InOut caller:
ep.AddStub(&mock.Stub{
BodyContains: "ping",
Body: []byte(`{"pong":true}`),
Headers: map[string]any{"Content-Type": "application/json"},
Status: 200,
})
Behavior notes¶
retainFirst+retainLasttogether keep the head and tail of the stream with a hole in the middle — useful for "first 10, last 10 out of 1M" forensics.TotalReceivedCount()always reports the true arrival count.assertPeriodis a tail-check. It runs after the expected count is met; if more messages arrive in that window, the assert fails.copyOnExchange=trueby default so a downstream step that mutates headers doesn't change what was recorded.- InOut callers.
ReturnReplyBody/ReturnReplyHeaderset the exchangeOutso the caller of amock://sees a reply. Stubs do the same withStub.Body/Headers/Status.
Source¶
pkg/component/mock/mock.go— Component, Endpoint, Producer, Consumer (always errors), Stub.- Tests:
pkg/component/mock/mock_test.go,pkg/component/mock/mock_parity_test.go.
See also¶
- For mocking outbound HTTP without a real server, see also the in-process
http-server://running on a test port.