{"id":12038,"library":"sinon","title":"Sinon.JS Test Spies, Stubs, and Mocks","description":"Sinon.js is a widely used, standalone, and test framework-agnostic JavaScript library providing test spies, stubs, and mocks for robust unit testing. The current stable version is 21.1.2. It maintains a consistent release cadence, frequently publishing updates and bug fixes across major versions. Key differentiators include its non-global pollution approach, ease of integration with any testing framework (like Mocha, Jest, or QUnit), and built-in fakes for browser APIs such as timers (setTimeout, setInterval) and XMLHttpRequest. It is designed to be easy to use and requires minimal setup, allowing developers to isolate and test specific units of code effectively by controlling their dependencies and behavior.","status":"active","version":"21.1.2","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/sinonjs/sinon","tags":["javascript","sinon","test","testing","unit","stub","spy","fake","time"],"install":[{"cmd":"npm install sinon","lang":"bash","label":"npm"},{"cmd":"yarn add sinon","lang":"bash","label":"yarn"},{"cmd":"pnpm add sinon","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Used internally by Sinon for faking global timers (setTimeout, setInterval, Date).","package":"fake-timers","optional":false},{"reason":"Provides fake XHR and fake server functionality, extracted from Sinon.js in v3.0.0.","package":"nise","optional":false}],"imports":[{"note":"While CommonJS `require` works, ESM `import` is the recommended modern approach. Sinon exports a default object containing all its utilities.","wrong":"const sinon = require('sinon');","symbol":"sinon","correct":"import sinon from 'sinon';"},{"note":"Sinon's core utilities like `stub`, `spy`, `mock`, `useFakeTimers` are properties of the default `sinon` object, not direct named exports from the package root.","wrong":"import { stub } from 'sinon';","symbol":"stub","correct":"import sinon from 'sinon'; sinon.stub(obj, 'method');"},{"note":"Access `useFakeTimers` via the default imported `sinon` object. It's crucial to call `clock.restore()` after tests to prevent global state pollution.","symbol":"useFakeTimers","correct":"import sinon from 'sinon'; const clock = sinon.useFakeTimers();"}],"quickstart":{"code":"import sinon from 'sinon';\n\n// Simulate an external API dependency\nclass ExternalAPI {\n  async getData(): Promise<string> {\n    // In a real application, this would make an actual network call\n    return Promise.resolve('Real Data From Server');\n  }\n}\n\n// Our code under test that depends on ExternalAPI\nclass MyService {\n  constructor(private api: ExternalAPI) {}\n\n  async processData(): Promise<string> {\n    const data = await this.api.getData();\n    return data.toUpperCase();\n  }\n}\n\nasync function runExample() {\n  const api = new ExternalAPI();\n  const service = new MyService(api);\n\n  // Create a stub for the API's getData method\n  const getDataStub = sinon.stub(api, 'getData');\n\n  // Configure the stub to return a predictable, mock value\n  getDataStub.resolves('Mocked Data');\n\n  // Call the method under test, which now uses the stubbed getData\n  const result = await service.processData();\n\n  console.log('Processed Result:', result); // Expected output: MOCKED DATA\n  console.log('getData was called once:', getDataStub.calledOnce); // Expected output: true\n\n  // Restore the original method to clean up after the test\n  getDataStub.restore();\n}\n\nrunExample().catch(console.error);","lang":"typescript","description":"Demonstrates stubbing an asynchronous dependency's method and verifying its interaction for isolated unit testing."},"warnings":[{"fix":"Consult the v3.0.0 migration guide on sinonjs.org for full details. For most users, continue to access functionalities like `sinon.useFakeXMLHttpRequest()` via the top-level `sinon` object.","message":"Sinon v3.0.0 removed several previously deprecated exports. Additionally, `fakeXhr`, `fakeServer`, and `fakeServerWithClock` functionalities were extracted into the `nise` package, though they were re-imported into Sinon's top-level API. Direct access to these modules via their old, internal paths may break.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Update your code to use `spy.resetHistory()` for clearing call history, arguments, and return values of a spy or stub. Use `spy.restore()` for reverting the original method.","message":"The `spy.reset()` method was deprecated in favor of `spy.resetHistory()` starting from v4.1.4. While `reset()` still works in current versions (21.x.x), it emits a deprecation warning and may be removed in future major releases.","severity":"deprecated","affected_versions":">=4.1.4"},{"fix":"Ensure your project is using Sinon.js v4.1.6 or a later version to avoid issues with `sinon.useFakeServer()`.","message":"Version 4.1.5 contained a bug where `sinon.useFakeServer()` could return an unexpected server type, leading to incorrect test behavior. This issue was promptly addressed in the following patch release.","severity":"gotcha","affected_versions":"4.1.5"},{"fix":"Always ensure `clock.restore()` is called in an `afterEach` or `after` hook within your test suite to revert global timers and `Date` to their original implementations.","message":"Failure to call `clock.restore()` after `sinon.useFakeTimers()` can lead to global state pollution, causing unexpected behavior in subsequent tests or other parts of the application that rely on real timer functions or the global `Date` object.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure Sinon is imported as a default export: `import sinon from 'sinon';` (ESM) or `const sinon = require('sinon');` (CommonJS), and then access `stub` as a property: `sinon.stub()`.","cause":"This error typically occurs when attempting to destructure `stub` as a named import (e.g., `import { stub } from 'sinon';`) or when `sinon` itself is not correctly imported.","error":"TypeError: sinon.stub is not a function"},{"fix":"Replace all calls to `spy.reset()` with `spy.resetHistory()` to clear the call history, arguments, and return values of a spy or stub. Use `spy.restore()` to revert the original method.","cause":"Attempting to use the `spy.reset()` method, which has been deprecated since v4.1.4 and is no longer the recommended way to clear a spy's state.","error":"TypeError: Cannot read properties of undefined (reading 'reset') OR console warning: 'spy.reset()' is deprecated. Use 'spy.resetHistory()' instead."},{"fix":"Verify that the method or property you intend to stub (`someMethodName`) exists on the object you are passing to `sinon.stub()`. This often happens with dynamic properties or when stubbing properties on prototypes that haven't been correctly inherited or defined.","cause":"Sinon cannot stub a method or property that does not exist on the target object at the moment `sinon.stub()` is called.","error":"Error: Cannot stub non-existent property 'someMethodName'"}],"ecosystem":"npm"}