JavaScript test spies, stubs and mocks for framework-agnostic unit testing.
—
Sinon's sandbox provides an isolated testing environment that manages all fakes (spies, stubs, mocks) and ensures proper cleanup between tests. Sandboxes prevent test interference and memory leaks by automatically tracking and restoring all created fakes.
Creates a new isolated sandbox for managing test fakes.
/**
* Creates a new sandbox instance for isolated testing
* @param options - Configuration options for the sandbox
* @returns A new sandbox instance
*/
function createSandbox(options?: SandboxOptions): SinonSandbox;
interface SandboxOptions {
/** Object to inject sandbox methods into */
injectInto?: object;
/** Properties to inject when using injectInto */
properties?: string[];
/** Automatically install fake timers */
useFakeTimers?: boolean | FakeTimerConfig;
/** Automatically install fake server (XMLHttpRequest) */
useFakeServer?: boolean;
}Usage Examples:
import { createSandbox } from "sinon";
// Basic sandbox
const sandbox = createSandbox();
// Sandbox with fake timers
const sandbox = createSandbox({
useFakeTimers: true
});
// Inject methods into test context
const testContext = {};
const sandbox = createSandbox({
injectInto: testContext,
properties: ["spy", "stub", "mock"]
});
// Now testContext.spy, testContext.stub, etc. are availableCore methods available on sandbox instances for creating and managing fakes.
interface SinonSandbox {
/** Create an anonymous spy */
spy(): SinonSpy;
/** Wrap a function with a spy */
spy<F extends Function>(func: F): SinonSpy<F>;
/** Replace object method with spy */
spy<T>(object: T, method: keyof T): SinonSpy;
/** Create an anonymous stub */
stub(): SinonStub;
/** Replace object method with stub */
stub<T>(object: T, method: keyof T): SinonStub;
/** Replace object method with custom stub implementation */
stub<T>(object: T, method: keyof T, func: Function): SinonStub;
/** Create a mock for an object */
mock(object: any): SinonMock;
/** Create a fake function */
fake(func?: Function): SinonFake;
/** Replace object property with a value */
replace<T>(object: T, property: keyof T, replacement: any): void & {
/** Replace object property using accessor-based assignment */
usingAccessor<T>(object: T, property: keyof T, replacement: any): void;
};
/** Replace object getter */
replaceGetter<T>(object: T, property: keyof T, getter: () => any): void;
/** Replace object setter */
replaceSetter<T>(object: T, property: keyof T, setter: (value: any) => void): void;
/** Install fake timers */
useFakeTimers(config?: FakeTimerConfig): SinonClock;
/** Access to fake timers clock after installation */
clock?: SinonClock;
/** Access to assertion methods */
assert: SinonAssert;
/** Access to matcher utilities */
match: SinonMatch;
}Replace object properties, getters, and setters with controlled values or functions for testing.
Usage Examples:
import { createSandbox } from "sinon";
const sandbox = createSandbox();
const myObject = {
config: { apiUrl: "https://api.example.com" },
get status() { return "active"; },
set status(value) { this._status = value; }
};
// Replace property value
sandbox.replace(myObject, "config", { apiUrl: "https://test-api.example.com" });
console.log(myObject.config.apiUrl); // "https://test-api.example.com"
// Replace using accessor-based assignment (for properties with setters)
sandbox.replace.usingAccessor(myObject, "status", "testing");
console.log(myObject.status); // "testing"
// Replace getter
sandbox.replaceGetter(myObject, "status", () => "mocked-status");
console.log(myObject.status); // "mocked-status"
// Replace setter
sandbox.replaceSetter(myObject, "status", (value) => {
console.log("Setter called with:", value);
});
myObject.status = "new-value"; // Logs: "Setter called with: new-value"
// Cleanup restores all replacements
sandbox.restore();Methods for managing the sandbox lifecycle and cleaning up created fakes.
interface SinonSandbox {
/** Restore all fakes in the sandbox to their original state */
restore(): void;
/** Reset call history for all fakes */
resetHistory(): void;
/** Reset behavior for all stubs to their default */
resetBehavior(): void;
/** Reset both history and behavior for all fakes */
reset(): void;
/** Verify all mock expectations in the sandbox */
verify(): void;
/** Verify all mocks and then restore */
verifyAndRestore(): void;
/** Get array of all fakes created by this sandbox */
getFakes(): SinonSpy[];
}Usage Examples:
import { createSandbox } from "sinon";
describe("User service", () => {
let sandbox;
beforeEach(() => {
sandbox = createSandbox();
});
afterEach(() => {
sandbox.restore(); // Clean up all fakes
});
it("should fetch user data", () => {
const fetchStub = sandbox.stub(api, "fetch").resolves({ id: 1 });
return userService.getUser(1).then(user => {
assert(fetchStub.calledOnce);
assert.equal(user.id, 1);
});
});
});The main sinon export is a pre-configured sandbox instance, providing all sandbox methods directly.
// The main sinon object extends SinonSandbox
interface SinonStatic extends SinonSandbox {
/** Create a new sandbox (same as createSandbox) */
createSandbox(options?: SandboxOptions): SinonSandbox;
/** Restore all methods on an object to their original implementation */
restoreObject(object: any): void;
/** Global access to matchers */
match: SinonMatch;
/** Global access to assertions */
assert: SinonAssert;
}Usage Examples:
import sinon from "sinon";
// Using the default sandbox
const spy = sinon.spy();
const stub = sinon.stub(obj, "method");
// Restore everything on the default sandbox
sinon.restore();
// Or create isolated sandboxes
const sandbox1 = sinon.createSandbox();
const sandbox2 = sinon.createSandbox();Sandbox memory management and leak detection capabilities.
interface SinonSandbox {
/** Threshold for detecting memory leaks (default: 10000) */
leakThreshold: number;
}Usage Examples:
const sandbox = createSandbox();
// Adjust leak detection threshold
sandbox.leakThreshold = 5000;
// In test cleanup, restore prevents memory leaks
afterEach(() => {
sandbox.restore();
});interface FakeTimerConfig {
/** Starting time for the fake clock */
now?: number | Date;
/** Array of timer methods to fake */
toFake?: ("setTimeout" | "clearTimeout" | "setInterval" | "clearInterval" | "Date")[];
/** Whether time should advance automatically */
shouldAdvanceTime?: boolean;
/** How much time should advance per tick */
advanceTimeDelta?: number;
}Install with Tessl CLI
npx tessl i tessl/npm-sinon