CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sinon

JavaScript test spies, stubs and mocks for framework-agnostic unit testing.

Pending
Overview
Eval results
Files

stubs.mddocs/

Test Stubs

Test stubs are spies with programmable behavior. They record calls like spies but also allow you to control return values, exceptions, and callback execution. Stubs are essential for isolating code under test from its dependencies.

Capabilities

Creating Stubs

Create stubs to replace functions with controlled behavior.

/**
 * Creates an anonymous stub with no default behavior
 * @returns New stub function
 */
function stub(): SinonStub;

/**
 * Replaces an object method with a stub
 * @param object - Object containing the method to stub
 * @param method - Method name to replace with stub
 * @returns Stub replacing the original method
 */
function stub<T>(object: T, method: keyof T): SinonStub;

/**
 * Replaces an object method with a stub that has custom implementation
 * @param object - Object containing the method to stub
 * @param method - Method name to replace
 * @param func - Custom implementation for the stub
 * @returns Stub with the provided implementation
 */
function stub<T>(object: T, method: keyof T, func: Function): SinonStub;

Usage Examples:

import { stub } from "sinon";

// Anonymous stub
const callback = stub();
callback.returns("test value");
console.log(callback()); // "test value"

// Stub object method
const user = { getName: () => "John" };
const nameStub = stub(user, "getName");
nameStub.returns("Jane");
console.log(user.getName()); // "Jane"

// Stub with custom implementation
const mathStub = stub(Math, "random");
mathStub.callsFake(() => 0.5);
console.log(Math.random()); // 0.5

Return Value Behaviors

Configure stubs to return specific values or follow patterns.

interface SinonStub extends SinonSpy {
  /**
   * Make stub return a specific value
   * @param value - Value to return when called
   * @returns The stub for chaining
   */
  returns(value: any): SinonStub;
  
  /**
   * Make stub return the argument at specified index
   * @param index - Argument index to return
   * @returns The stub for chaining
   */
  returnsArg(index: number): SinonStub;
  
  /**
   * Make stub return the `this` context
   * @returns The stub for chaining
   */
  returnsThis(): SinonStub;
}

Usage Examples:

const stub = sinon.stub();

// Return specific value
stub.returns(42);
console.log(stub()); // 42

// Return argument
stub.returnsArg(1);
console.log(stub("first", "second")); // "second"

// Return this context
const obj = { method: stub.returnsThis() };
console.log(obj.method() === obj); // true

Exception Behaviors

Configure stubs to throw exceptions.

interface SinonStub extends SinonSpy {
  /**
   * Make stub throw an exception
   * @param error - Error to throw (creates generic Error if omitted)
   * @returns The stub for chaining
   */
  throws(error?: any): SinonStub;
  
  /**
   * Make stub throw an exception with specific type and message
   * @param type - Error type name
   * @param message - Error message
   * @returns The stub for chaining
   */
  throws(type: string, message?: string): SinonStub;
  
  /**
   * Make stub throw the argument at specified index
   * @param index - Argument index to throw
   * @returns The stub for chaining
   */
  throwsArg(index: number): SinonStub;
}

Usage Examples:

const stub = sinon.stub();

// Throw generic error
stub.throws();
// stub() throws Error

// Throw specific error
stub.throws(new TypeError("Invalid argument"));
// stub() throws TypeError: Invalid argument

// Throw with type and message
stub.throws("RangeError", "Value out of range");
// stub() throws RangeError: Value out of range

// Throw argument
stub.throwsArg(0);
// stub(new Error("test")) throws the provided error

Promise Behaviors

Configure stubs to work with async/await and Promises.

interface SinonStub extends SinonSpy {
  /**
   * Make stub return a resolved Promise
   * @param value - Value to resolve with
   * @returns The stub for chaining
   */
  resolves(value?: any): SinonStub;
  
  /**
   * Make stub return a rejected Promise
   * @param error - Error to reject with
   * @returns The stub for chaining
   */
  rejects(error?: any): SinonStub;
  
  /**
   * Make stub resolve with the argument at specified index
   * @param index - Argument index to resolve with
   * @returns The stub for chaining
   */
  resolvesArg(index: number): SinonStub;
  
  /**
   * Make stub resolve with the `this` context
   * @returns The stub for chaining
   */
  resolvesThis(): SinonStub;
}

Usage Examples:

const stub = sinon.stub();

// Resolve with value
stub.resolves({ data: "success" });
const result = await stub();
console.log(result); // { data: "success" }

// Reject with error
stub.rejects(new Error("API failed"));
try {
  await stub();
} catch (error) {
  console.log(error.message); // "API failed"
}

// Resolve with argument
stub.resolvesArg(0);
const data = await stub("hello world");
console.log(data); // "hello world"

Callback Behaviors

Configure stubs to call functions passed as arguments (callbacks).

interface SinonStub extends SinonSpy {
  /**
   * Make stub call the callback at specified argument index
   * @param index - Argument index of the callback function
   * @returns The stub for chaining
   */
  callsArg(index: number): SinonStub;
  
  /**
   * Make stub call the callback with specific arguments
   * @param index - Argument index of the callback function
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  callsArgWith(index: number, ...args: any[]): SinonStub;
  
  /**
   * Make stub call the callback with specific `this` context
   * @param index - Argument index of the callback function
   * @param context - `this` context for the callback
   * @returns The stub for chaining
   */
  callsArgOn(index: number, context: any): SinonStub;
  
  /**
   * Make stub call the callback with context and arguments
   * @param index - Argument index of the callback function
   * @param context - `this` context for the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  callsArgOnWith(index: number, context: any, ...args: any[]): SinonStub;
  
  /**
   * Make stub call the first callback argument (leftmost)
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yields(...args: any[]): SinonStub;
  
  /**
   * Make stub call the last callback argument (rightmost)
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsRight(...args: any[]): SinonStub;
  
  /**
   * Make stub call the first callback with specific `this` context
   * @param context - `this` context for the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsOn(context: any, ...args: any[]): SinonStub;
  
  /**
   * Make stub call a callback property with arguments
   * @param property - Property name containing the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsTo(property: string, ...args: any[]): SinonStub;
  
  /**
   * Make stub call a callback property with context and arguments
   * @param property - Property name containing the callback
   * @param context - `this` context for the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsToOn(property: string, context: any, ...args: any[]): SinonStub;
}

Usage Examples:

const stub = sinon.stub();

// Call callback at index 1
stub.callsArg(1);
stub("first", (x) => console.log(x)); // Callback called with undefined

// Call callback with arguments
stub.callsArgWith(0, "hello", "world");
stub((a, b) => console.log(a, b)); // Logs: "hello world"

// Call first callback found
stub.yields("error", null);
stub(null, (err, data) => {
  console.log(err, data); // Logs: "error" null
});

// Call callback property
const options = { success: (data) => console.log(data) };
stub.yieldsTo("success", "completed");
stub(options); // Logs: "completed"

Async Callback Behaviors

Asynchronous versions of callback behaviors.

interface SinonStub extends SinonSpy {
  /**
   * Make stub call callback asynchronously at next tick
   * @param index - Argument index of the callback function
   * @returns The stub for chaining
   */
  callsArgAsync(index: number): SinonStub;
  
  /**
   * Make stub call callback asynchronously with arguments
   * @param index - Argument index of the callback function
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  callsArgWithAsync(index: number, ...args: any[]): SinonStub;
  
  /**
   * Make stub call callback asynchronously with context
   * @param index - Argument index of the callback function
   * @param context - `this` context for the callback
   * @returns The stub for chaining
   */
  callsArgOnAsync(index: number, context: any): SinonStub;
  
  /**
   * Make stub call callback asynchronously with context and arguments
   * @param index - Argument index of the callback function
   * @param context - `this` context for the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  callsArgOnWithAsync(index: number, context: any, ...args: any[]): SinonStub;
  
  /**
   * Make stub call first callback asynchronously
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsAsync(...args: any[]): SinonStub;
  
  /**
   * Make stub call first callback asynchronously with context
   * @param context - `this` context for the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsOnAsync(context: any, ...args: any[]): SinonStub;
  
  /**
   * Make stub call callback property asynchronously
   * @param property - Property name containing the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsToAsync(property: string, ...args: any[]): SinonStub;
  
  /**
   * Make stub call callback property asynchronously with context
   * @param property - Property name containing the callback
   * @param context - `this` context for the callback
   * @param args - Arguments to pass to the callback
   * @returns The stub for chaining
   */
  yieldsToOnAsync(property: string, context: any, ...args: any[]): SinonStub;
}

Custom Implementation Behaviors

Configure stubs with custom implementations or pass-through behavior.

interface SinonStub extends SinonSpy {
  /**
   * Make stub call a custom function when invoked
   * @param func - Custom function implementation
   * @returns The stub for chaining
   */
  callsFake(func: Function): SinonStub;
  
  /**
   * Make stub call the original method (if stubbing object method)
   * @returns The stub for chaining
   */
  callsThrough(): SinonStub;
  
  /**
   * Make stub call the original method when used as constructor
   * @returns The stub for chaining
   */
  callsThroughWithNew(): SinonStub;
}

Usage Examples:

// Custom implementation
const stub = sinon.stub();
stub.callsFake((x, y) => x + y);
console.log(stub(2, 3)); // 5

// Call through to original
const obj = { method: (x) => x * 2 };
const stub = sinon.stub(obj, "method");
stub.callsThrough(); // Calls original implementation
console.log(obj.method(5)); // 10 (original behavior)

Conditional Behaviors

Configure different behaviors for specific calls or arguments.

interface SinonStub extends SinonSpy {
  /**
   * Configure behavior for calls with specific arguments
   * @param args - Arguments that trigger this behavior
   * @returns Stub configured for these arguments
   */
  withArgs(...args: any[]): SinonStub;
  
  /**
   * Configure behavior for a specific call number
   * @param index - Zero-based call index
   * @returns Stub configured for this call
   */
  onCall(index: number): SinonStub;
  
  /**
   * Configure behavior for the first call
   * @returns Stub configured for first call
   */
  onFirstCall(): SinonStub;
  
  /**
   * Configure behavior for the second call
   * @returns Stub configured for second call
   */
  onSecondCall(): SinonStub;
  
  /**
   * Configure behavior for the third call
   * @returns Stub configured for third call
   */
  onThirdCall(): SinonStub;
}

Usage Examples:

const stub = sinon.stub();

// Different behavior for different arguments
stub.withArgs("hello").returns("world");
stub.withArgs("foo").returns("bar");
console.log(stub("hello")); // "world"
console.log(stub("foo")); // "bar"

// Different behavior for different calls
stub.onFirstCall().returns("first");
stub.onSecondCall().returns("second");
stub.onThirdCall().throws();
console.log(stub()); // "first"
console.log(stub()); // "second"
// stub(); // throws

Property Behaviors

Configure stubs for object property access (getters/setters).

interface SinonStub extends SinonSpy {
  /**
   * Configure stub as a getter that returns value when property is accessed
   * @param func - Getter function
   * @returns The stub for chaining
   */
  get(func: () => any): SinonStub;
  
  /**
   * Configure stub as a setter that calls function when property is set
   * @param func - Setter function
   * @returns The stub for chaining
   */
  set(func: (value: any) => void): SinonStub;
  
  /**
   * Configure stub as a property with a specific value
   * @param value - Property value
   * @returns The stub for chaining
   */
  value(value: any): SinonStub;
}

Stub Lifecycle

Methods for managing stub state and behavior.

interface SinonStub extends SinonSpy {
  /**
   * Reset all stub behaviors to default (but keep call history)
   */
  resetBehavior(): void;
  
  /**
   * Reset call history (but keep behaviors)
   */
  resetHistory(): void;
  
  /**
   * Reset both behaviors and call history
   */
  reset(): void;
  
  /**
   * Restore original method (for stubs on object methods)
   */
  restore(): void;
}

Usage Examples:

const obj = { method: () => "original" };
const stub = sinon.stub(obj, "method");

// Configure behavior
stub.returns("stubbed");
console.log(obj.method()); // "stubbed"

// Reset behavior but keep history
stub.resetBehavior();
console.log(obj.method()); // "original" (back to original)
console.log(stub.called); // true (history preserved)

// Reset everything
stub.reset();
console.log(stub.called); // false (history cleared)

// Restore original method
stub.restore();
// obj.method is now completely restored

Types

// Stub extends all spy functionality
interface SinonStub extends SinonSpy {
  // All stub-specific methods documented above
}

// Generic stub interface for typed functions
interface SinonStub<F extends Function = Function> extends SinonStub {
  (...args: Parameters<F>): ReturnType<F>;
}

Install with Tessl CLI

npx tessl i tessl/npm-sinon

docs

assertions.md

fakes.md

index.md

matchers.md

mocks.md

promises.md

sandbox.md

spies.md

stubs.md

timers.md

tile.json