JavaScript test spies, stubs and mocks for framework-agnostic unit testing.
—
Test mocks provide pre-programmed expectations for verifying that code interacts with dependencies correctly. Unlike spies and stubs, mocks define expected behavior upfront and verify that those expectations are met.
Create mock objects with expectations for method calls.
/**
* Creates a mock for an object, allowing expectations to be set on its methods
* @param object - Object to create mock for
* @returns Mock object for setting expectations
*/
function mock(object: any): SinonMock;
/**
* Creates an anonymous mock with a name for better error messages
* @param name - Name for the anonymous mock
* @returns Anonymous mock expectation
*/
function mock(name?: string): SinonExpectation;Usage Examples:
import { mock } from "sinon";
// Mock an object
const user = { getName: () => "John", setName: (name) => {} };
const userMock = mock(user);
// Anonymous mock
const callback = mock("callback");Interface for managing mocks on objects with multiple methods.
interface SinonMock {
/**
* Create an expectation for a specific method
* @param method - Method name to create expectation for
* @returns Expectation object for configuring behavior and verification
*/
expects(method: string): SinonExpectation;
/**
* Restore all mocked methods to their original implementations
*/
restore(): void;
/**
* Verify that all expectations on this mock have been satisfied
* @throws Error if any expectations are not met
*/
verify(): void;
}Usage Examples:
const api = {
fetch: (url) => Promise.resolve({}),
cache: (key, value) => {},
log: (message) => console.log(message)
};
const apiMock = sinon.mock(api);
// Set up expectations
apiMock.expects("fetch").once().withArgs("/users").returns(Promise.resolve({ users: [] }));
apiMock.expects("cache").twice();
apiMock.expects("log").never();
// Code under test would call api methods here
await api.fetch("/users");
api.cache("users", []);
api.cache("timestamp", Date.now());
// Verify all expectations were met
apiMock.verify(); // Passes if all expectations satisfied
apiMock.restore(); // Restore original methodsConfigure individual method expectations with call counts and arguments.
interface SinonExpectation {
/**
* Expect method to be called exactly once
* @returns The expectation for chaining
*/
once(): SinonExpectation;
/**
* Expect method to be called exactly twice
* @returns The expectation for chaining
*/
twice(): SinonExpectation;
/**
* Expect method to be called exactly three times
* @returns The expectation for chaining
*/
thrice(): SinonExpectation;
/**
* Expect method to be called an exact number of times
* @param count - Expected call count
* @returns The expectation for chaining
*/
exactly(count: number): SinonExpectation;
/**
* Expect method to be called at least a certain number of times
* @param count - Minimum expected call count
* @returns The expectation for chaining
*/
atLeast(count: number): SinonExpectation;
/**
* Expect method to be called at most a certain number of times
* @param count - Maximum expected call count
* @returns The expectation for chaining
*/
atMost(count: number): SinonExpectation;
/**
* Expect method to never be called
* @returns The expectation for chaining
*/
never(): SinonExpectation;
}Usage Examples:
const obj = { method: () => {} };
const mock = sinon.mock(obj);
// Exact call counts
mock.expects("method").once();
mock.expects("method").exactly(3);
// Range of call counts
mock.expects("method").atLeast(2);
mock.expects("method").atMost(5);
// Never called
mock.expects("method").never();Configure expectations for method arguments.
interface SinonExpectation {
/**
* Expect method to be called with specific arguments (partial match)
* @param args - Expected arguments
* @returns The expectation for chaining
*/
withArgs(...args: any[]): SinonExpectation;
/**
* Expect method to be called with exact arguments (exact match)
* @param args - Expected exact arguments
* @returns The expectation for chaining
*/
withExactArgs(...args: any[]): SinonExpectation;
/**
* Expect method to be called with arguments matching patterns
* @param matchers - Matcher patterns for arguments
* @returns The expectation for chaining
*/
withMatch(...matchers: any[]): SinonExpectation;
}Usage Examples:
const obj = { process: (data, options) => {} };
const mock = sinon.mock(obj);
// Specific arguments
mock.expects("process").withArgs("test data", { format: "json" });
// Exact arguments (no additional args allowed)
mock.expects("process").withExactArgs("exact", "match");
// Matching patterns
import { match } from "sinon";
mock.expects("process").withMatch(match.string, match.object);Configure expectations for method call context.
interface SinonExpectation {
/**
* Expect method to be called with specific `this` context
* @param thisValue - Expected `this` value
* @returns The expectation for chaining
*/
on(thisValue: any): SinonExpectation;
}Usage Examples:
const context = { name: "test" };
const obj = { method: function() { return this.name; } };
const mock = sinon.mock(obj);
mock.expects("method").on(context);
// Call method with expected context
obj.method.call(context); // Satisfies expectationConfigure what the mocked method should do when called (same as stub behaviors).
interface SinonExpectation {
/**
* Make expectation return a specific value
* @param value - Value to return
* @returns The expectation for chaining
*/
returns(value: any): SinonExpectation;
/**
* Make expectation return argument at specified index
* @param index - Argument index to return
* @returns The expectation for chaining
*/
returnsArg(index: number): SinonExpectation;
/**
* Make expectation return `this` context
* @returns The expectation for chaining
*/
returnsThis(): SinonExpectation;
/**
* Make expectation throw an exception
* @param error - Error to throw
* @returns The expectation for chaining
*/
throws(error?: any): SinonExpectation;
/**
* Make expectation throw exception with type and message
* @param type - Error type
* @param message - Error message
* @returns The expectation for chaining
*/
throws(type: string, message?: string): SinonExpectation;
/**
* Make expectation call a custom function
* @param func - Custom function to call
* @returns The expectation for chaining
*/
callsFake(func: Function): SinonExpectation;
/**
* Make expectation call the original method
* @returns The expectation for chaining
*/
callsThrough(): SinonExpectation;
/**
* Make expectation return resolved Promise
* @param value - Value to resolve with
* @returns The expectation for chaining
*/
resolves(value?: any): SinonExpectation;
/**
* Make expectation return rejected Promise
* @param error - Error to reject with
* @returns The expectation for chaining
*/
rejects(error?: any): SinonExpectation;
/**
* Make expectation call callback at specified index
* @param index - Callback argument index
* @returns The expectation for chaining
*/
callsArg(index: number): SinonExpectation;
/**
* Make expectation call callback with arguments
* @param index - Callback argument index
* @param args - Arguments for callback
* @returns The expectation for chaining
*/
callsArgWith(index: number, ...args: any[]): SinonExpectation;
/**
* Make expectation call first callback with arguments
* @param args - Arguments for callback
* @returns The expectation for chaining
*/
yields(...args: any[]): SinonExpectation;
}Usage Examples:
const obj = {
getValue: () => {},
processData: (data, callback) => {},
fetchUser: (id) => {}
};
const mock = sinon.mock(obj);
// Return value
mock.expects("getValue").returns(42);
// Throw exception
mock.expects("getValue").throws(new Error("Not found"));
// Promise behaviors
mock.expects("fetchUser").resolves({ id: 1, name: "John" });
// Callback behaviors
mock.expects("processData").yields(null, "processed");
// Custom implementation
mock.expects("getValue").callsFake(() => Date.now());Methods for verifying that expectations are met.
interface SinonExpectation {
/**
* Verify that this individual expectation has been satisfied
* @throws Error if expectation is not met
*/
verify(): void;
}
interface SinonMock {
/**
* Verify all expectations on this mock
* @throws Error if any expectation is not met
*/
verify(): void;
}Usage Examples:
const obj = { method: () => {} };
const mock = sinon.mock(obj);
const expectation = mock.expects("method").once();
// Call the method
obj.method();
// Verify individual expectation
expectation.verify(); // Passes
// Or verify entire mock
mock.verify(); // Passes if all expectations satisfiedCombining multiple expectations and complex verification scenarios.
Usage Examples:
// Complex mock scenario
const database = {
connect: () => {},
query: (sql) => {},
disconnect: () => {}
};
const dbMock = sinon.mock(database);
// Set up call sequence expectations
dbMock.expects("connect").once().returns(true);
dbMock.expects("query")
.twice()
.withArgs(sinon.match.string)
.returns([{ id: 1 }]);
dbMock.expects("disconnect").once();
// Code under test
database.connect();
database.query("SELECT * FROM users");
database.query("SELECT * FROM posts");
database.disconnect();
// Verify all expectations
try {
dbMock.verify();
console.log("All database interactions verified");
} catch (error) {
console.error("Mock verification failed:", error.message);
} finally {
dbMock.restore();
}// Anonymous mock for callback testing
const onSuccess = sinon.mock("onSuccess").once().withArgs("result");
const onError = sinon.mock("onError").never();
// Code under test would call these
onSuccess("result"); // Satisfies expectation
try {
onSuccess.verify(); // Passes
onError.verify(); // Passes (never called as expected)
} catch (error) {
console.error("Callback expectations not met");
}interface SinonMock {
expects(method: string): SinonExpectation;
restore(): void;
verify(): void;
}
interface SinonExpectation {
// Call count expectations
once(): SinonExpectation;
twice(): SinonExpectation;
thrice(): SinonExpectation;
exactly(count: number): SinonExpectation;
atLeast(count: number): SinonExpectation;
atMost(count: number): SinonExpectation;
never(): SinonExpectation;
// Argument expectations
withArgs(...args: any[]): SinonExpectation;
withExactArgs(...args: any[]): SinonExpectation;
withMatch(...matchers: any[]): SinonExpectation;
// Context expectations
on(thisValue: any): SinonExpectation;
// Behavior configuration (extends stub behaviors)
returns(value: any): SinonExpectation;
throws(error?: any): SinonExpectation;
resolves(value?: any): SinonExpectation;
rejects(error?: any): SinonExpectation;
callsFake(func: Function): SinonExpectation;
callsThrough(): SinonExpectation;
yields(...args: any[]): SinonExpectation;
// Verification
verify(): void;
}Install with Tessl CLI
npx tessl i tessl/npm-sinon