### Initialize fake timers with configuration options Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md This example shows how to initialize fake timers with a configuration object, allowing for advanced customization. Options include setting the starting time (`now`), specifying which functions to fake (`toFake`), enabling automatic time advancement (`shouldAdvanceTime`), and specifying a custom global object (`global`). ```javascript var clock = sinon.useFakeTimers(config); ``` -------------------------------- ### Spy Getter and Setter Example - Sinon.JS Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/spies.md An example demonstrating how to use `sinon.spy` to wrap the getter and setter of an object's property. It shows how to interact with the property and then assert that the spies have been called. ```javascript var object = { get test() { return this.property; }, set test(value) { this.property = value * 2; }, }; var spy = sinon.spy(object, "test", ["get", "set"]); object.test = 42; assert(spy.set.calledOnce); assert.equals(object.test, 84); assert(spy.get.calledOnce); ``` -------------------------------- ### Serve Sinon.JS Documentation Locally Source: https://github.com/sinonjs/sinon/blob/main/docs/CONTRIBUTING.md This snippet shows how to navigate to the documentation directory, install dependencies using bundler, and then build, serve, and live-reload the documentation site. The site can be accessed at http://localhost:4000/. ```shell cd docs bundle install npm run serve-docs ``` -------------------------------- ### Install Sinon.JS using npm Source: https://github.com/sinonjs/sinon/blob/main/docs/index.md Installs the latest release of Sinon.JS using the Node Package Manager (npm). This is the standard way to add Sinon to your project for use with Node.js or browserify/webpack build systems. ```shell npm install sinon ``` -------------------------------- ### Load Mocha Root Hook via Command Line Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/general-setup.md This shell command demonstrates how to load a Mocha root hook file using the `--require` option. This is necessary for the `mochaHooks` configuration to be recognized and executed. ```shell mocha --require tests/hooks.js ``` -------------------------------- ### Using Default Sandbox in Sinon 5+ Source: https://github.com/sinonjs/sinon/blob/main/docs/guides/migration-guide.md Demonstrates how to use the default sandbox in Sinon 5.0.0 and later, simplifying test setup by removing the need for manual sandbox creation and restoration. This approach makes test code more concise. ```javascript describe("myFunction", function () { afterEach(function () { sinon.restore(); }); it("should make pie"); }); ``` -------------------------------- ### Initialize fake timers with a specific start time Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md This snippet demonstrates initializing fake timers with a custom starting timestamp or Date object. This allows tests to begin at a specific point in time, which can be useful for time-sensitive logic. The provided timestamp or Date's getTime() value will be used as the initial time. ```javascript var clock = sinon.useFakeTimers(now); ``` -------------------------------- ### Manual Sandbox Creation (Pre-Sinon 5) Source: https://github.com/sinonjs/sinon/blob/main/docs/guides/migration-guide.md Illustrates the older method of manually creating and managing sandboxes in Sinon versions prior to 5.0.0. This approach requires explicit sandbox creation and restoration in test setup and teardown. ```javascript const sandbox = sinon.createSandbox(); describe("myFunction", function () { afterEach(function () { sandbox.restore(); }); it("should make pie"); }); ``` -------------------------------- ### Example: Calling the Last Callback (Sinon.JS) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/stubs.md This example shows how to use `callArg(1)` to invoke the second callback (index 1) passed to a stubbed function. It defines a stub that accepts two callbacks and then explicitly calls the second one, logging a message. ```javascript "calling the last callback": function () { var callback = sinon.stub(); callback(function () { console.log("Success!"); }, function () { console.log("Oh noes!"); }); callback.callArg(1); // Logs "Oh noes!" } ``` -------------------------------- ### Example: Faking AJAX Success with yieldsTo (Sinon.JS) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/stubs.md This example demonstrates how to use `stub.yieldsTo` to fake a successful AJAX request. It stubs `jQuery.ajax` and simulates a success callback with specific data, then asserts that the provided success handler receives this data. ```javascript "test should fake successful ajax request": function () { sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]); jQuery.ajax({ success: function (data) { assertEquals([1, 2, 3], data); } }); } ``` -------------------------------- ### Complete Integration Test Example with Sinon.JS Source: https://context7.com/sinonjs/sinon/llms.txt This example demonstrates a full integration test for an OrderService class using Sinon.JS. It mocks external dependencies like payment gateways and email services to isolate the OrderService logic. The tests cover successful order placement and error handling for out-of-stock scenarios, showcasing Sinon's stubbing, assertion, and call order verification capabilities. ```javascript const sinon = require('sinon'); const assert = require('assert'); // System under test class OrderService { constructor(paymentGateway, emailService, inventory) { this.paymentGateway = paymentGateway; this.emailService = emailService; this.inventory = inventory; } async placeOrder(order) { // Check inventory const available = await this.inventory.check(order.productId, order.quantity); if (!available) { throw new Error('Out of stock'); } // Process payment const payment = await this.paymentGateway.charge(order.customerId, order.total); if (!payment.success) { throw new Error('Payment failed'); } // Reserve inventory await this.inventory.reserve(order.productId, order.quantity); // Send confirmation await this.emailService.sendConfirmation(order.customerEmail, order); return { orderId: payment.transactionId, status: 'confirmed' }; } } // Tests describe('OrderService', function() { let sandbox; let orderService; let paymentGateway; let emailService; let inventory; beforeEach(function() { sandbox = sinon.createSandbox(); paymentGateway = { charge: sandbox.stub() }; emailService = { sendConfirmation: sandbox.stub() }; inventory = { check: sandbox.stub(), reserve: sandbox.stub() }; orderService = new OrderService(paymentGateway, emailService, inventory); }); afterEach(function() { sandbox.restore(); }); it('should place order successfully', async function() { // Arrange const order = { productId: 'PROD-1', quantity: 2, customerId: 'CUST-1', customerEmail: 'test@example.com', total: 99.99 }; inventory.check.resolves(true); inventory.reserve.resolves(); paymentGateway.charge.resolves({ success: true, transactionId: 'TXN-123' }); emailService.sendConfirmation.resolves(); // Act const result = await orderService.placeOrder(order); // Assert assert.deepEqual(result, { orderId: 'TXN-123', status: 'confirmed' }); sinon.assert.calledOnce(inventory.check); sinon.assert.calledWith(inventory.check, 'PROD-1', 2); sinon.assert.calledOnce(paymentGateway.charge); sinon.assert.calledWith(paymentGateway.charge, 'CUST-1', 99.99); sinon.assert.calledOnce(emailService.sendConfirmation); sinon.assert.calledWith(emailService.sendConfirmation, 'test@example.com', order); sinon.assert.callOrder( inventory.check, paymentGateway.charge, inventory.reserve, emailService.sendConfirmation ); }); it('should throw when out of stock', async function() { inventory.check.resolves(false); await assert.rejects( () => orderService.placeOrder({ productId: 'PROD-1', quantity: 100 }), { message: 'Out of stock' } ); sinon.assert.notCalled(paymentGateway.charge); }); }); ``` -------------------------------- ### Install Fake Timers with Automatic Time Advancement (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md Installs fake timers at a specific date and enables automatic time advancement. Timers will fire automatically without manual intervention, simplifying tests involving asynchronous operations. This example demonstrates the default advancement interval of 20ms. ```javascript var clock = sinon.useFakeTimers({ now: 1483228800000, shouldAdvanceTime: true, }); setImmediate(function () { console.log("tick"); //will print after 20ms }); setTimeout(function () { console.log("tock"); //will print after 20ms }, 15); setTimeout(function () { console.log("tack"); //will print after 40ms }, 35); ``` -------------------------------- ### Test async function with async/await and fake timers (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/lolex-async-promises.md This example illustrates testing an `async` function using `async/await` syntax combined with fake timers. It shows how to advance the clock and then `await` the promise returned by the async function, asserting its resolved value for fast, synchronous-like testing. ```javascript // test.js it("should return 42 after 1000ms", async () => { const promise = maker.asyncReturnAfterOneSecond(); clock.tick(1000); const result = await promise; assert.equal(result, 42); // PASS }); ``` -------------------------------- ### Restore Default Sandbox in Mocha (afterEach hook) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/general-setup.md This JavaScript snippet demonstrates how to restore the default Sinon.JS sandbox after each test using the `afterEach` hook in Mocha. This is crucial for preventing memory leaks. ```javascript afterEach(() => { // Restore the default sandbox here sinon.restore(); }); ``` -------------------------------- ### Restore Default Sandbox in Mocha (root hook) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/general-setup.md This JavaScript snippet shows how to configure a root hook in Mocha (v8.0.0+) to automatically restore the default Sinon.JS sandbox after every test. This requires loading the hook file using the `--require` option. ```javascript // tests/hooks.js // Restores the default sandbox after every test exports.mochaHooks = { afterEach() { sinon.restore(); }, }; ``` -------------------------------- ### Verify Links with Makefile Target Source: https://github.com/sinonjs/sinon/blob/main/docs/README.md This snippet demonstrates how to use the Makefile target 'check-links' to verify internal and external links in the Sinon.JS documentation. It requires checking out the 'releases' branch, installing dependencies, building the site, and then running the link check. This process may require local adjustments for checking changes on different branches. ```bash git checkout releases make install make build make check-links ``` -------------------------------- ### Sinon Test Suite for Mocking Dependency Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This is a Sinon.JS test suite written in TypeScript using Mocha and Chai. It demonstrates how to stub the 'toBeMocked' function from the './other' module to return a mocked value. It also includes an import for './init', which is likely responsible for test setup. ```typescript import sinon from "sinon"; import "./init"; import * as Other from "./other"; import { main } from "./main"; import { expect } from "chai"; const sandbox = sinon.createSandbox(); describe("main", () => { let mocked; it("should mock", () => { mocked = sandbox.stub(Other, "toBeMocked").returns("mocked"); main(); expect(mocked.called).to.be.true; }); }); ``` -------------------------------- ### Mocking with Sinon Auto-Cleanup and Accessors Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This example demonstrates how to use Sinon's auto-cleanup feature with accessors to mock a function. It involves defining a mutable export and then using `sandbox.replace.usingAccessor` to replace it during tests. This approach simplifies cleanup by allowing Sinon to manage the restoration of the original value. ```typescript function _toBeMocked() { return "I am the original function"; } export let toBeMocked = _toBeMocked; export const myMocks = { set toBeMocked(mockImplementation) { toBeMocked = mockImplementation; }, get toBeMocked() { return _toBeMocked; }, }; ``` ```typescript describe("main", () => { after(() => sandbox.restore()) it("should mock", () => { mocked = sandbox.fake.returns("mocked"); sandbox.replace.usingAccessor(Other.myMocks, 'toBeMocked', mocked) main(); expect(mocked.called).to.be.true; }); ``` -------------------------------- ### Example Usage of Sinon Assertions with Spies Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/assertions.md This example demonstrates how to use Sinon.JS assertions to verify the behavior of a spy. It shows a test case where a subscriber is expected to be called once with a specific message. The assertions `sinon.assert.calledOnce` and `sinon.assert.calledWith` are used to check the spy's invocation. ```javascript "test should call subscribers with message as first argument" : function () { var message = "an example message"; var spy = sinon.spy(); PubSub.subscribe(message, spy); PubSub.publishSync(message, "some payload"); sinon.assert.calledOnce(spy); sinon.assert.calledWith(spy, message); } ``` -------------------------------- ### Initialize fake timers with default settings Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md This code snippet shows how to initialize Sinon's fake timers with default settings. It replaces global timer functions and Date with custom implementations bound to a clock object. The clock starts at the UNIX epoch (timestamp 0). ```javascript var clock = sinon.useFakeTimers(); ``` -------------------------------- ### Restore Default Sandbox in Jasmine Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/general-setup.md This JavaScript snippet illustrates how to restore the default Sinon.JS sandbox within each `describe` block in Jasmine. Similar to Mocha, this prevents memory leaks by ensuring the sandbox is cleaned up after tests. ```javascript describe("My test suite", () => { afterEach(() => { // Restore the default sandbox here sinon.restore(); }); }); ``` -------------------------------- ### Asserting fuzzy arguments with Sinon.JS matchers Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/matchers.md This example demonstrates how to use Sinon.JS matchers to assert function call arguments with varying degrees of specificity. It utilizes `sinon.match` with object properties and nested matchers to verify the arguments passed to a spy. This is useful for testing complex data structures where exact matches are not always required. ```javascript var book = { pages: 42, author: "cjno", id: { isbn10: "0596517742", isbn13: "978-0596517748" } }; var spy = sinon.spy(); spy(book); sinon.assert.calledWith(spy, sinon.match({ author: "cjno" })); sinon.assert.calledWith(spy, sinon.match.has("pages", 42)); sinon.assert.calledWith(spy, sinon.match.has("id", sinon.match.has("isbn13", "978-0596517748"))); ``` -------------------------------- ### Test animation with fake timers Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md This example demonstrates how to use Sinon's fake timers to test an animation function. It sets up a clock, performs an animation, advances the clock by a specified duration, and then asserts the final state of the animated element. This allows for synchronous testing of asynchronous operations. ```javascript { setUp: function () { this.clock = sinon.useFakeTimers(); }, tearDown: function () { this.clock.restore(); }, "test should animate element over 500ms" : function(){ var el = jQuery("
"); el.appendTo(document.body); el.animate({ height: "200px", width: "200px" }); this.clock.tick(510); assertEquals("200px", el.css("height")); assertEquals("200px", el.css("width")); } } ``` -------------------------------- ### Sinon.JS: Demonstrating `fake.throws()` and `fake.threw()` (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/CHANGES.md This snippet demonstrates the usage of `sinon.fake.throws()` to create a fake function that throws an error, and the `fake.threw()` method which is intended to check if the fake function threw a specific error. The example highlights a potential discrepancy or outdated usage of `threw(obj)`. ```javascript const sinon = require("sinon"); const o = { pie: "apple" }; const f = sinon.fake.throws(o); f(); // this is supposed to return true f.threw(o); // => false ``` -------------------------------- ### Stub asynchronous dependency returning a Promise in Node.js with Sinon Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/stub-dependency.md This example illustrates stubbing an asynchronous dependency that returns a Promise in a Node.js environment using Sinon. It utilizes `async/await` keywords in the test methods to handle the asynchronous nature of the dependency. The stubbing is set up within a `beforeEach` hook and restored in an `afterEach` hook to ensure a clean state for each test. This approach is useful for testing modules that interact with APIs or other asynchronous operations. ```javascript const assert = require("assert"); const sinon = require("sinon"); const userUtils = require("./userUtils"); const userApi = require("./userApi"); function aUser(id) { return { id, email: `someemail@user${id}.com`, first_name: `firstName${id}`, last_name: `lastName${id}`, avatar: `https://www.somepage${id}.com`, }; } describe("userUtils", function () { let getPageOfUsersStub; beforeEach(function () { getPageOfUsersStub = sinon.stub(userApi, "getPageOfUsers"); }); afterEach(function () { getPageOfUsersStub.restore(); }); describe("when a single page of users exists", function () { it("should return users from that page", async function () { // Arrange const pageOfUsers = { page: 1, total_pages: 1, data: [aUser(1), aUser(2), aUser(3)], }; getPageOfUsersStub.returns(Promise.resolve(pageOfUsers)); // Act const result = await userUtils.getAllUsers(); // Assert assert.equal(result.length, 3); assert.equal(getPageOfUsersStub.calledOnce, true); }); }); describe("when multiple pages of users exists", function () { it("should return a combined list of all users", async function () { // Arrange const pageOfUsers1 = { page: 1, total_pages: 2, data: [aUser(1), aUser(2), aUser(3)], }; const pageOfUsers2 = { page: 2, total_pages: 2, data: [aUser(4), aUser(5)], }; getPageOfUsersStub.withArgs(1).returns(Promise.resolve(pageOfUsers1)); getPageOfUsersStub.withArgs(2).returns(Promise.resolve(pageOfUsers2)); // Act const result = await userUtils.getAllUsers(); // Assert assert.equal(result.length, 5); assert.equal(getPageOfUsersStub.callCount, 2); }); }); }); ``` -------------------------------- ### Install Fake Timers with Specific Timers Faked (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md Installs fake timers at a specific date and fakes only 'setTimeout' and 'process.nextTick'. This is useful for isolating timer behavior in tests. It requires Sinon.js and an assertion library like 'assert'. ```javascript var clock = sinon.useFakeTimers({ now: 1483228800000, toFake: ["setTimeout", "nextTick"], }); var called = false; process.nextTick(function () { called = true; }); clock.runAll(); //forces nextTick calls to flush synchronously assert(called); //true ``` -------------------------------- ### Create and verify a mock object in JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/mocks.md Demonstrates how to create a mock for an object's method, set expectations on its usage (e.g., call count, exceptions), and then verify if those expectations were met. This is useful for testing interactions with dependencies. ```javascript "test should call all subscribers when exceptions": function () { var myAPI = { method: function () {} }; var spy = sinon.spy(); var mock = sinon.mock(myAPI); mock.expects("method").once().throws(); PubSub.subscribe("message", myAPI.method); PubSub.subscribe("message", spy); PubSub.publishSync("message", undefined); mock.verify(); assert(spy.calledOnce); } ``` -------------------------------- ### Update sandbox.create() config for fake timers Source: https://github.com/sinonjs/sinon/blob/main/docs/guides/migration-guide.md Configuration for `sinon.sandbox.create()` has changed, particularly for fake timers. The `useFaketimers` option now requires a nested `toFake` property to specify which methods to fake. This change centralizes timer faking configuration within the sandbox creation process. ```javascript { useFaketimers: { toFake: ["setTimeout", "setInterval"] } } ``` -------------------------------- ### Create and Use a Sandbox for Test Cleanup - JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/sandbox.md Demonstrates creating a sandbox to stub and restore a method within a test suite. The sandbox simplifies cleanup by restoring all fakes created through it in the `afterEach` block. ```javascript const sandbox = require("sinon").createSandbox(); const myAPI = { hello: function () {} }; describe("myAPI.hello method", function () { beforeEach(function () { // stub out the `hello` method sandbox.stub(myAPI, "hello"); }); afterEach(function () { // completely restore all fakes created through the sandbox sandbox.restore(); }); it("should be called once", function () { myAPI.hello(); sandbox.assert.calledOnce(myAPI.hello); }); it("should be called twice", function () { myAPI.hello(); myAPI.hello(); sandbox.assert.calledTwice(myAPI.hello); }); }); ``` -------------------------------- ### Publish New Release to NPM Registry Source: https://github.com/sinonjs/sinon/blob/main/RELEASE.md Publishes the current version of the package to the npm registry, making it available for installation by other projects. ```shell npm publish ``` -------------------------------- ### Get All Call Records from a Spy (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/spies.md The `spy.getCalls()` method returns an array containing all call records logged by the spy. This provides a comprehensive history of how the spy was invoked. ```javascript var spyCalls = spy.getCalls(); ``` -------------------------------- ### Mocking Node.js Modules with Quibble Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This snippet illustrates how to mock a Node.js module using the Quibble library, which is integrated with Sinon's sandbox. It shows how to replace a module's exports and then use the mocked function within the main application logic. This is useful for isolating dependencies during testing. ```typescript describe("main module", () => { let mocked, main; before(() => { mocked = sandbox.stub().returns("mocked"); quibble("./other", { toBeMocked: mocked }); ({ main } = require("./main")); }); it("should mock", () => { main(); expect(mocked.called).to.be.true; }); }); ``` -------------------------------- ### Get a specific spy call by index - Sinon.JS Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/spy-call.md Retrieves the nth call object for a spied function. This is useful for detailed verification of multiple calls. It requires the Sinon.JS library. ```javascript sinon.spy(jQuery, "ajax"); jQuery.ajax("/stuffs"); var spyCall = jQuery.ajax.getCall(0); assertEquals("/stuffs", spyCall.args[0]); ``` -------------------------------- ### Create Fake Promise with Custom Executor - JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/promises.md Creates a fake promise with a custom executor function, allowing for specific logic within the promise's setup. The executor receives `resolve` and `reject` functions. ```javascript var promise = sinon.promise(function (resolve, reject) { // ... }); ``` -------------------------------- ### Dependency Injection for Stubbing - JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/faq.md Demonstrates how to use dependency injection to make code more testable and avoid property descriptor errors when stubbing. Instead of directly stubbing an imported module, the dependency is passed as a parameter, allowing for easier replacement with a stub in tests. This approach is generally more robust than direct module stubbing. ```javascript // Instead of this: import { toBeMocked } from "./module"; sinon.stub(module, "toBeMocked"); // This might fail // Do this: function myFunction(dependency = toBeMocked) { return dependency(); } // In tests: const stub = sinon.stub(); myFunction(stub); ``` -------------------------------- ### Configure logging for FakeServer Source: https://github.com/sinonjs/sinon/blob/main/docs/guides/migration-guide.md The global `sinon.log` and `sinon.logError` functions for configuring logging in `FakeServer`, `FakeXMLHttpRequest`, and `FakeXDomainRequest` have been removed. Logging should now be configured on a per-use basis when creating these objects, allowing for more isolated logging configurations. ```javascript var sinon = require("sinon"); var myFakeServer = sinon.fakeServer.create({ logger: function (msg) { // your logging impl } }); ``` -------------------------------- ### Manual Mocking with Dependency Injection in Sinon.js Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This JavaScript test code demonstrates manual mocking using the dependency injection pattern. It saves the original function, applies a Sinon stub, and ensures the original function is restored in the `after` hook, providing a clean way to test components with external dependencies. ```javascript describe("main", () => { let mocked; let original = Other.toBeMocked; after(() => Other._setToBeMocked(original)) it("should mock", () => { mocked = sandbox.stub().returns("mocked"); Other._setToBeMocked(mocked) main(); expect(mocked.called).to.be.true; }); ``` -------------------------------- ### Wrap Property Accessors with Spy - Sinon.JS Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/spies.md Creates spies for the 'get' and/or 'set' accessors of an object's property. The spies record calls to these accessors and behave like the original ones. The original accessors can be restored individually. ```javascript var spy = sinon.spy(object, "property", ["get", "set"]); ``` -------------------------------- ### Create a stub instance of a constructor - JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/stubs.md Illustrates using `sinon.createStubInstance` to create a stub object that mimics an instance of a given constructor without actually invoking the constructor. This is useful for isolating dependencies in tests. Optional overrides can be provided to pre-configure stubbed methods. ```javascript class MyConstructor { constructor() { this.value = 1; } foo() { return 'bar'; } } var stubInstance = sinon.createStubInstance(MyConstructor, { foo: sinon.stub().returns('baz') }); console.log(stubInstance.value); // undefined (constructor not called) console.log(stubInstance.foo()); // 'baz' ``` -------------------------------- ### Using Fakes for Immutable Test Doubles in Sinon.js Source: https://context7.com/sinonjs/sinon/llms.txt Introduces Sinon.js fakes as immutable functions with predefined behavior, combining the simplicity of spies with the control of stubs. Examples include fakes that return values, throw errors, resolve promises, or yield to callbacks. ```javascript const sinon = require('sinon'); // Fake that returns a value const returnsHello = sinon.fake.returns('hello'); console.log(returnsHello()); // 'hello' console.log(returnsHello.calledOnce); // true // Fake that throws const throwsError = sinon.fake.throws(new Error('Oops')); try { throwsError(); } catch (e) { console.log(e.message); // 'Oops' } // Fake that resolves a promise const resolvesData = sinon.fake.resolves({ data: 'async result' }); resolvesData().then(result => { console.log(result); // { data: 'async result' } }); // Fake that yields to callback const yieldsCallback = sinon.fake.yields(null, 'result'); yieldsCallback(function(err, data) { console.log(data); // 'result' }); // Replace property on object with fake const myModule = { fetch: function() {} }; const fakeFetch = sinon.fake.resolves({ status: 200 }); sinon.replace(myModule, 'fetch', fakeFetch); myModule.fetch().then(result => { console.log(result.status); // 200 }); sinon.restore(); // Restore original ``` -------------------------------- ### Configuring SWC Plugin for Mutable CommonJS Exports Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This JSON configuration snippet shows how to enable the `swc_mut_cjs_exports` plugin within SWC. This plugin modifies the transpilation output to ensure that CommonJS exports are configurable, which is necessary for certain mocking scenarios with Sinon.js. ```json { "experimental": { "plugins": [[ "swc_mut_cjs_exports", {} ]] }, } ``` -------------------------------- ### Test async function returning a value after delay with fake timers (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/lolex-async-promises.md This example shows how to test an `async` function that resolves a promise after a delay. It utilizes fake timers to advance time and then asserts the resolved value of the promise, making the test run almost instantly. ```javascript // maker.js module.exports.asyncReturnAfterOneSecond = async () => { // Using util.promisify would look nicer, but there is a lolex issue // blocking this at the moment: https://github.com/sinonjs/lolex/pull/227 const setTimeoutPromise = (timeout) => { return new Promise((resolve) => setTimeout(resolve, timeout)); }; await setTimeoutPromise(1000); return 42; }; // test.js it("should return 42 after one second", () => { const promise = maker.asyncReturnAfterOneSecond(); clock.tick(1000); return promise.then((result) => assert.equal(result, 42)); // PASS }); ``` -------------------------------- ### Get a Specific Call Record from a Spy (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/spies.md The `spy.getCall(n)` method retrieves the nth call record from the spy's history. Negative indices can be used to access calls from the end of the history (e.g., `spy.getCall(-1)` for the last call). This is valuable for detailed verification of individual function invocations. ```javascript var spyCall = spy.getCall(n); ``` -------------------------------- ### Using Fake Timers with Async/Await (JavaScript) Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/fake-timers.md Demonstrates how to use Sinon.js fake timers with modern JavaScript 'async/await' syntax. It highlights the importance of using 'tickAsync' to properly handle promise resolutions and timer callbacks in asynchronous test scenarios. Note that 'await' on async functions would hang the clock. ```javascript async function asyncFn() { await wait(100); console.log('resolved 1', Date.now()); await wait(10); console.log('resolved 2', Date.now()); } async function test() { const clock = sinon.useFakeTimers(); setTimeout(() => console.log('timeout', Date.now()), 200); asyncFn(); // NOTE: no `await` here - it would hang, as the clock is stopped await clock.tickAsync(200); } // test() prints: // - resolved 1 100 // - resolved 2 110 // - timeout 200 ``` -------------------------------- ### Sinon.JS hasNested Matcher for Deep Property Checking Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/matchers.md The `sinon.match.hasNested` matcher verifies if a value contains a specific nested property path. It supports dot and bracket notation for property access, similar to Lodash's `get`. An optional expectation can be provided for deep comparison of the nested property's value. ```javascript sinon.match.hasNested("a[0].b.c"); // Where actual is something like var actual = { a: [{ b: { c: 3 } }] }; sinon.match.hasNested("a.b.c"); // Where actual is something like var actual = { a: { b: { c: 3 } } }; ``` -------------------------------- ### Create Stub Instance with Sinon.JS Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/utils.md Creates a new object with the given constructor as its prototype and stubs all implemented functions. The constructor is not invoked. Useful for testing class instances without actual instantiation. ```javascript class Container { contains(item) { /* ... */ } } var stubContainer = sinon.createStubInstance(Container); stubContainer.contains.returns(false); stubContainer.contains.withArgs("item").returns(true); ``` -------------------------------- ### Create Sandbox with Fake Timers Enabled - JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/sandbox.md Shows how to create a Sinon sandbox with fake timers enabled. This configuration allows the sandbox to manage timers like `setTimeout` and `setInterval` for testing time-dependent code. ```javascript const sandbox = sinon.createSandbox({ useFakeTimers: true, }); ``` -------------------------------- ### Create and Use Stubs in JavaScript Source: https://context7.com/sinonjs/sinon/llms.txt Illustrates the creation and usage of stubs in Sinon.JS, which replace functions with pre-programmed behavior. Stubs can be configured to return specific values, handle different arguments, or stub methods on objects. The original method can be restored using `stub.restore()`. ```javascript const sinon = require('sinon'); // Create a stub that returns a value const stub = sinon.stub(); stub.returns(42); console.log(stub()); // 42 // Stub different behaviors for different arguments const calculate = sinon.stub(); calculate.withArgs(1).returns('one'); calculate.withArgs(2).returns('two'); calculate.returns('unknown'); console.log(calculate(1)); // 'one' console.log(calculate(2)); // 'two' console.log(calculate(99)); // 'unknown' // Stub on object method const api = { fetch: function(url) { /* real implementation */ } }; sinon.stub(api, 'fetch').resolves({ data: 'mocked' }); api.fetch('/users').then(response => { console.log(response); // { data: 'mocked' } }); api.fetch.restore(); ``` -------------------------------- ### Replacing a Getter with a Stub in Sinon.js Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This JavaScript code demonstrates how to use Sinon.js to replace a getter property on an object. It's used in conjunction with SWC plugins that make properties configurable, allowing Sinon to effectively mock or stub the getter's behavior. ```javascript const stub = sandbox.fake.returns("mocked"); sandbox.replaceGetter(Other, "toBeMocked", () => stub); ``` -------------------------------- ### Create Controllable Promises with Sinon.JS Source: https://context7.com/sinonjs/sinon/llms.txt This snippet demonstrates how to create and control fake promises using Sinon.JS. It covers manual resolution and rejection, accessing promise state, and using controllable promises in asynchronous tests. No external dependencies are required beyond Sinon.JS. ```javascript const sinon = require('sinon'); // Create fake promise const promise = sinon.promise(); console.log(promise.status); // 'pending' // Resolve manually promise.resolve('success'); console.log(promise.status); // 'resolved' console.log(promise.resolvedValue); // 'success' // Create with executor const executor = sinon.fake(); const promise2 = sinon.promise(executor); console.log(executor.calledOnce); // true // Reject manually const promise3 = sinon.promise(); promise3.reject(new Error('Failed')); console.log(promise3.status); // 'rejected' console.log(promise3.rejectedValue); // Error: Failed // Use in async tests async function testAsync() { const service = { getData: function() { return sinon.promise(); } }; const resultPromise = service.getData(); // Later, resolve it resultPromise.resolve({ data: 'test' }); const result = await resultPromise; console.log(result); // { data: 'test' } } ``` -------------------------------- ### Sinon.js Fake Timers - Time Control Source: https://context7.com/sinonjs/sinon/llms.txt Sinon.js provides fake timers to control time-related functions like `setTimeout`, `setInterval`, and `Date`. You can use `sinon.useFakeTimers()` to enable them, advance time with `clock.tick()`, or start at a specific time. Advanced configurations allow faking specific functions and auto-advancing time. ```javascript const sinon = require('sinon'); // Basic usage const clock = sinon.useFakeTimers(); let called = false; setTimeout(function() { called = true; }, 1000); console.log(called); // false clock.tick(1000); // Advance time by 1000ms console.log(called); // true clock.restore(); // Start at specific time const clock2 = sinon.useFakeTimers(new Date('2024-01-01')); console.log(new Date().toISOString()); // '2024-01-01T00:00:00.000Z' clock2.restore(); // Advanced configuration const clock3 = sinon.useFakeTimers({ now: 1483228800000, // Jan 1, 2017 toFake: ['setTimeout', 'setInterval', 'Date'], // Only fake specific functions shouldAdvanceTime: true // Auto-advance based on real time }); // Async-friendly tick async function asyncTest() { const clock = sinon.useFakeTimers(); let resolved = false; setTimeout(() => { resolved = true; }, 100); await clock.tickAsync(100); // Works with promises console.log(resolved); // true clock.restore(); } asyncTest(); ``` -------------------------------- ### Sinon.JS Matchers for Flexible Argument Verification Source: https://context7.com/sinonjs/sinon/llms.txt Demonstrates using Sinon.JS matchers to perform flexible or precise argument verification for spies and stubs. It covers type, array, and custom matchers, as well as combining matchers and stubbing with arguments. ```javascript const sinon = require('sinon'); const spy = sinon.spy(); spy({ name: 'John', age: 30, roles: ['admin', 'user'], metadata: { created: new Date() } }); // Type matchers sinon.assert.calledWith(spy, sinon.match.object); sinon.assert.calledWith(spy, sinon.match.has('name')); sinon.assert.calledWith(spy, sinon.match.has('name', 'John')); sinon.assert.calledWith(spy, sinon.match.has('age', sinon.match.number)); // Array matchers sinon.assert.calledWith(spy, sinon.match.has('roles', sinon.match.array.contains(['admin']))); // Combining matchers const stringOrNumber = sinon.match.string.or(sinon.match.number); const hasNameAndAge = sinon.match.has('name').and(sinon.match.has('age')); // Stub with matchers const stub = sinon.stub(); stub.withArgs(sinon.match.string).returns('string input'); stub.withArgs(sinon.match.number).returns('number input'); stub.withArgs(sinon.match({ type: 'special' })).returns('special object'); console.log(stub('hello')); // 'string input' console.log(stub(42)); // 'number input' console.log(stub({ type: 'special', extra: true })); // 'special object' // Custom matcher const positiveNumber = sinon.match(function(value) { return typeof value === 'number' && value > 0; }, 'positive number'); stub.withArgs(positiveNumber).returns('positive'); console.log(stub(5)); // 'positive' console.log(stub(-1)); // undefined (no match) ``` -------------------------------- ### Mocks API Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/mocks.md This section details the Sinon.JS Mocks API, including creating mocks, setting expectations, and managing mock lifecycle. ```APIDOC ## Mocks API ### Properties #### `var mock = sinon.mock(obj);` Creates a mock for the provided object. Does not change the object, but returns a mock object to set expectations on the object's methods. #### `var expectation = mock.expects("method");` Overrides `obj.method` with a mock function and returns it. See [expectations](#expectations) below. #### `mock.restore();` Restores all mocked methods. #### `mock.verify();` Verifies all expectations on the mock. If any expectation is not satisfied, an exception is thrown. Also restores the mocked methods. ``` -------------------------------- ### Dependency Injection for Mocking in TypeScript Source: https://github.com/sinonjs/sinon/blob/main/docs/_howto/typescript-swc.md This TypeScript code illustrates a pure dependency injection approach for mocking. It involves exporting the function to be mocked and providing a setter function to replace it, allowing external control over the implementation without relying on transpiler configurations. ```typescript function _toBeMocked() { return "I am the original function"; } export let toBeMocked = _toBeMocked; export function _setToBeMocked(mockImplementation) { toBeMocked = mockImplementation; } ``` -------------------------------- ### Use sandbox.useFakeServer instead of sandbox.useFakeXMLHttpRequest Source: https://github.com/sinonjs/sinon/blob/main/docs/guides/migration-guide.md The `sandbox.useFakeXMLHttpRequest` method in Sinon v2.x now maps directly to `sinon.useFakeXMLHttpRequest` with sandboxing. To achieve the behavior of Sinon 1.x where `useFakeXMLHttpRequest` was equivalent to `useFakeServer`, replace `sandbox.useFakeXMLHttpRequest` with `sandbox.useFakeServer`. ```javascript sandbox.useFakeServer(); ``` -------------------------------- ### Sinon.JS mock object API in JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/release-source/release/mocks.md Details the core API for creating and managing mock objects in Sinon.JS. It covers creating a mock from an object, defining expectations on its methods, restoring mocked methods, and verifying all expectations. ```javascript var mock = sinon.mock(obj); ``` ```javascript var expectation = mock.expects("method"); ``` ```javascript mock.restore(); ``` ```javascript mock.verify(); ``` -------------------------------- ### Dynamic Imports for Stubbing - JavaScript Source: https://github.com/sinonjs/sinon/blob/main/docs/faq.md Illustrates using dynamic imports to stub properties, which can sometimes circumvent transpilation issues that lead to property descriptor errors. By dynamically importing the module, Sinon can potentially access and stub the property before it becomes immutable. ```javascript // In your test const module = await import("./module"); sinon.stub(module, "toBeMocked"); ``` -------------------------------- ### Configuring Mock Expectations API in Sinon.js Source: https://context7.com/sinonjs/sinon/llms.txt Details the various configurations available in Sinon.js's Mock Expectations API for setting precise conditions on method calls, such as call counts, arguments, and context. ```javascript const sinon = require('sinon'); const calculator = { add: function(a, b) { return a + b; } }; const mock = sinon.mock(calculator); // Various expectation configurations mock.expects('add').atLeast(1); // Called 1+ times mock.expects('add').atMost(3); // Called at most 3 times mock.expects('add').exactly(2); // Called exactly 2 times mock.expects('add').never(); // Never called mock.expects('add').once(); // Called exactly once mock.expects('add').twice(); // Called exactly twice mock.expects('add').thrice(); // Called exactly three times mock.expects('add').withArgs(1, 2); // Called with specific args mock.expects('add').withExactArgs(1, 2); // Called with only these args mock.expects('add').on(someObject); // Called with specific this mock.verify(); mock.restore(); ```