A mockable Promise for testing asynchronous operations in distributed systems.
MockChain is a lightweight, fully mockable Promise subclass that allows you to test asynchronous communication among peers, servers, or browser clients.
Each async operation can be wrapped in a MockChain, giving you full control over its resolution or rejection in tests.
🔗 Visit the blog: mockchain.blog.fizzwiz.cloud
- Mockable Promises: Wrap any asynchronous operation and control its outcome.
- Configurable auto-start: Pass
autoStart = falseto delay execution until.mock()or.fail()is manually invoked. - Delayed resolution/rejection: Use
mockAfterandfailAfterto simulate network latency. - Factory methods: Conveniently wrap fetch requests, WebSocket messages, or any event emitter.
- Chainable: Preserves native Promise chaining while remaining mockable.
- Root access: Use
.rootto access the first node in a chain. - Parent navigation: Access the previous node via
.parent.
npm install @fizzwiz/mockchain<script src="https://cdn.jsdelivr.net/npm/@fizzwiz/mockchain/dist/mockchain.bundle.js"></script>
<script>
const { MockChain } = window.mockchain;
</script>The global mockchain object exposes all classes.
import { MockChain } from '@fizzwiz/mockchain';
// Implement a mockable async-like method
function doFetch(url, autoStart = true) {
const chain = MockChain.from(fetch(url), autoStart)
.then(res => res.json());
return chain;
}
// Test the method in isolation
const chain = doFetch(undefined, false); // get a non-auto-start chain
chain.root.mock(new Response(JSON.stringify({ ok: true }))); // trigger the chain manually
const result = await chain; // the final resolved value
console.log(result); // -> { ok: true }mock(value)— force resolve withvalue.fail(error)— force reject witherror.mockAfter(ms, value)— resolve after a delay.failAfter(ms, error)— reject after a delay.- Standard
then,catch, andfinallymethods are overridden to preserve mockability. .root— reference the top-level node of the chain..parent— reference the previous node in the chain.
resolve(value)— create a resolved MockChain.reject(reason)— create a rejected MockChain.from(valueOrPromise, autoStart = true, parent = null)— convert any Promise or value into a MockChain.fromResponse(url, opts, autoStart = true)— wrap a fetch request.fromMessage(ws, isMessage?, attach = false, autoStart = true)— wrap WebSocket messages.fromEvent(emitter, eventName, isEvent?, attach = false, autoStart = true)— wrap any Node.js or browser event.
💡 Note:
All static constructors support the autoStart flag:
- When
autoStart = true, the executor runs immediately (like a normal Promise). - When
autoStart = false, execution is deferred until.mock()or.fail()is called. fromResponse→.mock()expects aResponseobject.fromMessage,fromEvent→.mock()expects the emitted event argument(s).
- Testing distributed node communication and behavior in isolation — without a live network.
- Simulating server or WebSocket responses in browser-based peers.
- Mocking event-driven behaviors during development or CI runs.
- Controlling intermediate steps in promise chains using
.parentor.root. - Debugging async flows built from extemporaneous arrow functions rather than dedicated functions.
Contributions, ideas, and feedback are welcome! Please open an issue or pull request on GitHub.
MIT © fizzwiz 🔗 mockchain.blog.fizzwiz.cloud