Postboy Help

Testing

@artstesh/postboy-testing (v3.4.x) is the BDD-style testing toolkit for applications built on the postboy message bus. Its core is PostboyServiceMock: a recording drop-in replacement for PostboyService. The mock captures every fired message, executed command, subscription, and callback result. Three services wrap the mock: given stubs bus behavior, then asserts recorded history, and waiter waits for asynchronous messages. All of them hang off a single test fixture, PostboyWorld.

Installation

Install the toolkit as a development dependency. Both peer dependencies must be present in the project.

npm install --save-dev @artstesh/postboy-testing

Package

Role

Version

@artstesh/postboy-testing

dev dependency

3.4.x

@artstesh/postboy

peer

^3.4.1 (3.4.x and 3.5.x supported)

rxjs

peer

^7

The toolkit is framework-agnostic and works with Jest, Vitest, Jasmine, or Karma.

The canonical flow

Every test follows the same five steps: create the world, stub with given, run the system under test with world.postboy, assert with then or await with waiter, dispose the world.

import { PostboyWorld } from '@artstesh/postboy-testing'; describe('OrderService', () => { let world: PostboyWorld; beforeEach(() => (world = new PostboyWorld())); // 1. create the world afterEach(() => world.dispose()); // 5. mandatory cleanup it('places an order and confirms it', async () => { world.given.executor(GetTaxRateExecutor, 0.2); // 2. stub the bus const service = new OrderService(world.postboy); // 3. run the SUT on the mock service.place(42); // 4a. synchronous assertions on recorded history world.then.fired(OrderPlacedEvent).once().with((e) => e.orderId === 42); // 4b. wait for messages that arrive later const confirmed = await world.waiter.waitFor(OrderConfirmedEvent); expect(confirmed.orderId).toBe(42); }); });

What the world gives you

Getter

Purpose

world.postboy

The recording mock bus. Inject it wherever the SUT expects a PostboyService.

world.given

Stub executors, callback responses, and pre-fired events.

world.then

Fluent assertions: fired, notFired, subscribed.

world.waiter

Promise-based waits: waitFor, waitForMany, waitForAny, waitForCallbackResult, waitForNone.

world.history

Direct access to recorded messages, callback results, and subscription counts.

world.mocks

Low-level stream mocks for cases given cannot express.

world.registry

Namespaced registrator for manual registration, required in strict mode.

Pitfalls

  • Recording only happens through world.postboy. A plain PostboyService records nothing.

  • world.dispose() must run after every test, and the world is not reusable afterwards.

  • By default the world is non-strict: unknown message types are auto-registered. In strict mode every type must be registered first.

Next steps

  • Quick start: a complete jest test, end to end.

  • PostboyWorld: world anatomy, strict mode, dispose discipline, escape hatches.

  • Assertions: the then builders, message history, and the boolean verifier.

  • Async waiters: the waitFor family and its options.

  • Recipes: task-based patterns for common test scenarios.

  • API reference: full signatures.

07 September 2026