Mock Setup with `given`
world.given is the Arrange phase API.
It lets you prepare the mock environment before your code acts — send initial events, set up pre‑canned callback responses, and mock executor return values.
Access it from the world:
All given methods return the same PostboyGivenService instance, so you can chain them in a natural, readable sequence.
Why use given?
Without given, you’d have to manually configure low‑level mock streams via world.mocks. given hides that complexity, giving you an expressive vocabulary for the Arrange phase.
Goal |
|
|---|---|
Fire a pre‑event before the test action |
|
Respond to a callback with a fixed value |
|
Return a stubbed value from an executor |
|
Under the hood, given delegates to world.mocks (PostboyMessageStreamService), so the mock bus is fully wired and ready.
given.event(message) – fire an event upfront
Sometimes your code expects a previous event to have occurred — for example, a “user logged in” event before the action under test. given.event() sends that event immediately to the mock bus.
What happens internally:
A replay subject for the message type is registered (so any future subscriber will also receive this event).
The message is fired through
world.postboy.fire().The message appears in the recorded history, just like any other fired message.
given.callback(Type, result) – mock a callback response
When your code uses PostboyCallbackMessage<T> to request data, you can pre‑define the answer.
What happens internally:
A subject for the callback message type is registered.
The mock subscribes to that message type.
When your code sends the callback via fireCallback, the mock intercepts it and calls message.finish(result), resolving the caller’s observable.
Example in a test:
Important: The mock answers every matching callback message sent during the test. If you need different answers for different calls, you may need to use the low‑level world.mocks.mockCallback() with a custom action function.
given.executor(Type, result) – mock an executor return value
Executors (PostboyExecutor<T>) are synchronous calls that return a value. With given.executor(), you stub that return value.
What happens internally:
The executor is registered with a handler function that simply returns
result.When your code calls
postboy.exec(new GetTaxRateExecutor()), the mock handler is invoked and returns the stub value.
Example:
Note that the executor itself is also recorded in history, so you can verify it was called with then.fired(GetTaxRateExecutor).
Chaining given methods
Because every method returns the same PostboyGivenService instance, you can build a complete initial state in a single statement.
This reads clearly as a scenario: “Given user logged in, a cart was created, fetching the cart returns empty, and the discount is 10%.”
Relationship to world.mocks
As noted, given is a high‑level wrapper around PostboyMessageStreamService (world.mocks). For most tests, given is sufficient. You only need world.mocks directly if you require:
Conditional mock behaviour depending on the message payload.
Multiple different answers for the same callback type.
Custom logic before calling finish(result).
Mocks that throw errors.
In those rare cases, refer to the advanced mocks section.
Best practices
Use
givenas the first block in your test — it sets the stage.Chain related setups to make the test context clear.
Don’t over‑mock — only set up what the test actually needs.
Remember that
given.event()fires immediately — it appears in history right away, not when the action happens.Check that your executor stubs match the expected return type — TypeScript will help, but runtime mismatches can cause surprises.
Next steps
With given you’ve mastered the Arrange phase. Now learn how to verify outcomes and handle asynchronous scenarios:
Then: assertions deep‑dive – every assertion method explained.
Waiter: async testing – wait for messages, silence, and callback results.
Recipes – copy‑paste patterns for common test scenarios.