a_mock Mocking Framework
a_mock is a focused JavaScript mocking framework designed to be used with any JavaScript testing framework. It enables the creation of both partial and strict mocks, offering granular control over function behavior for testing purposes. Developers can define specific expectations for arguments (single, multiple, arrays, and complex objects), specify return values, configure exceptions to be thrown, and manage call repetition. The library provides capabilities for ignoring arguments or entire calls when precision isn't necessary. It is currently at version 2.0.5 and includes TypeScript type definitions, facilitating its use in TypeScript projects. While a_mock emphasizes explicit expectation setup and strict argument matching, particularly for object arguments, its core utility lies in providing a clear, declarative API for creating test doubles without imposing a specific test runner or assertion library. The release cadence for a_mock is not explicitly detailed in the provided documentation, but it presents as a stable, utility-focused library for fundamental mocking scenarios.
Common errors
-
throws unexpected arguments
cause A strict mock was called with arguments that do not match any active `expect()` criteria, or all predefined expectations have already been consumed.fixAdd an `expect()` clause for the specific arguments being used, configure the expectation with `repeatAny()`, or use `ignore()` / `ignoreAll()` if argument matching is not necessary for that call path. -
throws unexpected arguments cause leaf properties are not equal
cause A mock expectation was set for an object (struct), but the object provided during the mock call did not have exactly matching leaf properties or values as defined in the expectation.fixVerify that the object passed to the mock call precisely matches the structure and leaf property values defined in the `mock.expect({ ... })` call. -
Error: invalid operation
cause The mock was specifically configured using `mock.expect().throw(errorInstance)` to throw a particular error for the current call.fixThis is expected behavior as per the mock's configuration. If unintended, review and remove or reconfigure the `throw()` expectation in your test setup.
Warnings
- gotcha Strict mocks (created without an original function) will throw an 'unexpected arguments' error if called with any arguments that do not precisely match a predefined expectation, or if called after all expectations have been consumed.
- gotcha When matching objects (referred to as 'structs' in the documentation), `a_mock` performs strict equality checks exclusively on *leaf properties*. This means an empty object expectation `{}` will not match any non-empty object provided, and all leaf property values in the actual object must exactly match those in the expected struct for a successful match.
- gotcha Expectations are consumed sequentially in the order they are defined. Once an `expect()` call is met and it's not configured with `repeatAny()`, that expectation is removed. Subsequent calls made after all expectations have been consumed will result in an 'unexpected arguments' error.
Install
-
npm install a_mock -
yarn add a_mock -
pnpm add a_mock
Imports
- mock
import aMock from 'a_mock';
import { mock } from 'a_mock'; - mock
const mockFactory = require('a_mock');const mockFactory = require('a_mock').mock; - MockInstance
import { MockInstance } from 'a_mock';import type { MockInstance } from 'a_mock';
Quickstart
import { mock } from 'a_mock';
// Minimal declaration for a_mock to satisfy TypeScript for quickstart
// In a real project, these types would be automatically available from 'a_mock'
declare module 'a_mock' {
interface MockExpectation {
return(value: any): MockExpectation;
throw(error: Error): MockExpectation;
repeat(count: number): MockExpectation;
repeatAny(): MockExpectation;
whenCalled(callback: (...args: any[]) => any): MockExpectation;
}
interface MockInstance extends Function {
expect(...args: any[]): MockExpectation;
ignore(): MockInstance;
ignoreAll(): { return(value: any): MockExpectation; };
}
function mock(originalFunction?: Function): MockInstance;
}
// Mocking a function that expects multiple arguments
const myMock = mock();
myMock.expect('firstArg1', 'secondArg1').return('fake1');
myMock.expect('firstArg2', 'secondArg2').return('fake2');
console.log('Call 1:', myMock('firstArg1', 'secondArg1')); // Expected: fake1
console.log('Call 2:', myMock('firstArg2', 'secondArg2')); // Expected: fake2
try {
myMock('foo');
} catch (e: any) {
console.error("Error on single arg call:", e.message); // Expected: throws unexpected arguments
}
try {
myMock('foo', 'bar');
} catch (e: any) {
console.error("Error on unexpected args:", e.message); // Expected: throws unexpected arguments
}
// Demonstrate a partial mock
const originalAdder = (a: number, b: number) => `Original sum: ${a + b}`;
const partialAdderMock = mock(originalAdder);
partialAdderMock.expect(10, 20).return('Mocked 10+20');
console.log('Partial mock call 1:', partialAdderMock(10, 20)); // Expected: Mocked 10+20
console.log('Partial mock call 2:', partialAdderMock(5, 5)); // Expected: Original sum: 10 (falls back)