{
  "doc": {
    "id": "app/guides/stubs-spies-and-clocks",
    "title": "Stubs, Spies, and Clocks: Cypress Guide",
    "description": "Learn how to use `cy.stub()`, `cy.spy()`, and `cy.clock()` in Cypress to manipulate your application's behavior and time.",
    "section": "app",
    "source_path": "/llm/markdown/app/guides/stubs-spies-and-clocks.md",
    "version": "24a73f8a97175663aaffd3b016289fb2a523a4ea",
    "updated_at": "2026-05-14T20:17:33.301Z",
    "headings": [
      {
        "id": "app/guides/stubs-spies-and-clocks#stubs-spies-and-clocks",
        "text": "Stubs, Spies, and Clocks",
        "level": 1
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#what-youll-learn",
        "text": "What you'll learn",
        "level": 5
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#libraries-and-tools",
        "text": "Libraries and Tools",
        "level": 2
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#common-scenarios",
        "text": "Common Scenarios",
        "level": 2
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#stubs",
        "text": "Stubs",
        "level": 3
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#common-scenarios",
        "text": "Common Scenarios:",
        "level": 4
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#spies",
        "text": "Spies",
        "level": 3
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#clock",
        "text": "Clock",
        "level": 3
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#common-scenarios",
        "text": "Common Scenarios",
        "level": 4
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#control-setinterval",
        "text": "Control setInterval",
        "level": 5
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#restore-the-clock",
        "text": "Restore the clock",
        "level": 5
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#assertions",
        "text": "Assertions",
        "level": 3
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#integration-and-extensions",
        "text": "Integration and Extensions",
        "level": 2
      },
      {
        "id": "app/guides/stubs-spies-and-clocks#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "app/guides/stubs-spies-and-clocks#what-youll-learn",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "What you'll learn",
      "heading_level": 5,
      "content_markdown": "##### What you'll learn\n\n*   How to use `cy.stub()`, `cy.spy()`, and `cy.clock()`\n*   Common scenarios for using stubs, spies, and clocks\n*   How to use assertions with stubs and spies\n\nCypress comes built in with the ability to stub and spy with [`cy.stub()`](/llm/markdown/api/commands/stub.md), [`cy.spy()`](/llm/markdown/api/commands/spy.md) or modify your application's time with [`cy.clock()`](/llm/markdown/api/commands/clock.md) - which lets you manipulate `Date`, `setTimeout`, `clearTimeout`, `setInterval`, or `clearInterval`.\n\nThese commands are useful when writing both **unit tests** and **integration tests**.\n",
      "section": "app",
      "anchors": [
        "what-youll-learn"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 99
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#libraries-and-tools",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Libraries and Tools",
      "heading_level": 2,
      "content_markdown": "## Libraries and Tools\n\nCypress automatically bundles and wraps these libraries:\n\n| Name | What it does |\n| --- | --- |\n| [`sinon`](http://sinonjs.org) | provides the [`cy.stub()`](/llm/markdown/api/commands/stub.md) and [`cy.spy()`](/llm/markdown/api/commands/spy.md) APIs |\n| [`lolex`](https://github.com/sinonjs/lolex) | provides the [`cy.clock()`](/llm/markdown/api/commands/clock.md) and [`cy.tick()`](/llm/markdown/api/commands/tick.md) APIs |\n| [`sinon-chai`](https://github.com/domenic/sinon-chai) | adds `chai` assertions for stubs and spies |\n\nYou can refer to each of these libraries' documentation for more examples and explanations.\n",
      "section": "app",
      "anchors": [
        "libraries-and-tools"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 91
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#common-scenarios",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Common Scenarios",
      "heading_level": 2,
      "content_markdown": "## Common Scenarios\n\n**Example test!**\n\n[Check out our example recipe testing spying, stubbing, and time](/llm/markdown/app/references/recipes.md#Stubbing-and-spying)\n\n### Stubs\n\nA stub is a way to modify a function and delegate control over its behavior to you (the programmer).\n\nA stub is most commonly used in a unit test but is still useful during some integration/e2e tests.\n\n```\n// create a standalone stub (generally for use in unit test)cy.stub()// replace obj.method() with a stubbed functioncy.stub(obj, 'method')// force obj.method() to return \"foo\"cy.stub(obj, 'method').returns('foo')// force obj.method() when called with \"bar\" argument to return \"foo\"cy.stub(obj, 'method').withArgs('bar').returns('foo')// force obj.method() to return a promise which resolves to \"foo\"cy.stub(obj, 'method').resolves('foo')// force obj.method() to return a promise rejected with an errorcy.stub(obj, 'method').rejects(new Error('foo'))\n```\n\nYou generally stub a function when it has side effects you are trying to control.\n\n#### Common Scenarios:\n\n*   You have a function that accepts a callback, and want to invoke the callback.\n*   Your function returns a `Promise`, and you want to automatically resolve or reject it.\n*   You have a function that wraps `window.location` and don't want your application to be navigated.\n*   You're trying to test your application's \"failure path\" by forcing things to fail.\n*   You're trying to test your application's \"happy path\" by forcing things to pass.\n*   You want to \"trick\" your application into thinking it's logged in or logged out.\n*   You're using `oauth` and want to stub login methods.\n\n**cy.stub()**\n\n[Read more about how to use `cy.stub()`](/llm/markdown/api/commands/stub.md).\n\n### Spies\n\nA spy gives you the ability to \"spy\" on a function, by letting you capture and then assert that the function was called with the right arguments, or that the function was called a certain number of times, or even what the return value was or what context the function was called with.\n\nA spy does **not** modify the behavior of the function - it is left perfectly intact. A spy is most useful when you are testing the contract between multiple functions and you don't care about the side effects the real function may create (if any).\n\n```\ncy.spy(obj, 'method')\n```\n\n**cy.spy()**\n\n[Read more about how to use `cy.spy()`](/llm/markdown/api/commands/spy.md).\n\n### Clock\n\nThere are situations when it is useful to control your application's `date` and `time` in order to override its behavior or avoid slow tests.\n\nWith [cy.clock()](/llm/markdown/api/commands/clock.md) you can control:\n\n*   `Date`\n*   `setTimeout`\n*   `setInterval`\n\n#### Common Scenarios\n\n##### Control `setInterval`\n\n*   You're polling something in your application with `setInterval` and want to control that.\n*   You have **throttled** or **debounced** functions which you want to control.\n\nOnce you've enabled [`cy.clock()`](/llm/markdown/api/commands/clock.md) you can control time by **ticking** it ahead by milliseconds.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)\n```\n\nYou can call [`cy.clock()`](/llm/markdown/api/commands/clock.md) **prior** to visiting your application and we will automatically bind it to the application on the next [`cy.visit()`](/llm/markdown/api/commands/visit.md). The same concept applies to mounting a component with [`cy.mount()`](/llm/markdown/api/commands/mount.md). We bind **before** any timers from your code can be invoked.\n\n##### Restore the clock\n\nYou can restore the clock and allow your application to resume normally without manipulating native global functions related to time. This is automatically called between tests.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)// more test code here// restore the clockcy.clock().then((clock) => {  clock.restore()})// more test code here\n```\n\nYou could also restore by using [.invoke()](/llm/markdown/api/commands/invoke.md) to invoke the `restore` function.\n\n```\ncy.clock().invoke('restore')\n```\n\n### Assertions\n\nOnce you have a `stub` or a `spy` in hand, you can then create assertions about them.\n\n```\nconst user = {  getName: (arg) => {    return arg  },  updateEmail: (arg) => {    return arg  },  fail: () => {    throw new Error('fail whale')  },}// force user.getName() to return \"Jane\"cy.stub(user, 'getName').returns('Jane Lane')// spy on updateEmail but do not change its behaviorcy.spy(user, 'updateEmail')// spy on fail but do not change its behaviorcy.spy(user, 'fail')// invoke getNameconst name = user.getName(123)// invoke updateEmailconst email = user.updateEmail('jane@devs.com')try {  // invoke fail  user.fail()} catch (e) {}expect(name).to.eq('Jane Lane') // trueexpect(user.getName).to.be.calledOnce // trueexpect(user.getName).not.to.be.calledTwice // trueexpect(user.getName).to.be.calledWith(123)expect(user.getName).to.be.calledWithExactly(123) // trueexpect(user.getName).to.be.calledOn(user) // trueexpect(email).to.eq('jane@devs.com') // trueexpect(user.updateEmail).to.be.calledWith('jane@devs.com') // trueexpect(user.updateEmail).to.have.returned('jane@devs.com') // trueexpect(user.fail).to.have.thrown('Error') // true\n```\n",
      "section": "app",
      "anchors": [
        "common-scenarios"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 875
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#stubs",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Stubs",
      "heading_level": 3,
      "content_markdown": "### Stubs\n\nA stub is a way to modify a function and delegate control over its behavior to you (the programmer).\n\nA stub is most commonly used in a unit test but is still useful during some integration/e2e tests.\n\n```\n// create a standalone stub (generally for use in unit test)cy.stub()// replace obj.method() with a stubbed functioncy.stub(obj, 'method')// force obj.method() to return \"foo\"cy.stub(obj, 'method').returns('foo')// force obj.method() when called with \"bar\" argument to return \"foo\"cy.stub(obj, 'method').withArgs('bar').returns('foo')// force obj.method() to return a promise which resolves to \"foo\"cy.stub(obj, 'method').resolves('foo')// force obj.method() to return a promise rejected with an errorcy.stub(obj, 'method').rejects(new Error('foo'))\n```\n\nYou generally stub a function when it has side effects you are trying to control.\n\n#### Common Scenarios:\n\n*   You have a function that accepts a callback, and want to invoke the callback.\n*   Your function returns a `Promise`, and you want to automatically resolve or reject it.\n*   You have a function that wraps `window.location` and don't want your application to be navigated.\n*   You're trying to test your application's \"failure path\" by forcing things to fail.\n*   You're trying to test your application's \"happy path\" by forcing things to pass.\n*   You want to \"trick\" your application into thinking it's logged in or logged out.\n*   You're using `oauth` and want to stub login methods.\n\n**cy.stub()**\n\n[Read more about how to use `cy.stub()`](/llm/markdown/api/commands/stub.md).\n",
      "section": "app",
      "anchors": [
        "stubs"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 299
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#common-scenarios",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Common Scenarios:",
      "heading_level": 4,
      "content_markdown": "#### Common Scenarios:\n\n*   You have a function that accepts a callback, and want to invoke the callback.\n*   Your function returns a `Promise`, and you want to automatically resolve or reject it.\n*   You have a function that wraps `window.location` and don't want your application to be navigated.\n*   You're trying to test your application's \"failure path\" by forcing things to fail.\n*   You're trying to test your application's \"happy path\" by forcing things to pass.\n*   You want to \"trick\" your application into thinking it's logged in or logged out.\n*   You're using `oauth` and want to stub login methods.\n\n**cy.stub()**\n\n[Read more about how to use `cy.stub()`](/llm/markdown/api/commands/stub.md).\n",
      "section": "app",
      "anchors": [
        "common-scenarios"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 147
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#spies",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Spies",
      "heading_level": 3,
      "content_markdown": "### Spies\n\nA spy gives you the ability to \"spy\" on a function, by letting you capture and then assert that the function was called with the right arguments, or that the function was called a certain number of times, or even what the return value was or what context the function was called with.\n\nA spy does **not** modify the behavior of the function - it is left perfectly intact. A spy is most useful when you are testing the contract between multiple functions and you don't care about the side effects the real function may create (if any).\n\n```\ncy.spy(obj, 'method')\n```\n\n**cy.spy()**\n\n[Read more about how to use `cy.spy()`](/llm/markdown/api/commands/spy.md).\n",
      "section": "app",
      "anchors": [
        "spies"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 149
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#clock",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Clock",
      "heading_level": 3,
      "content_markdown": "### Clock\n\nThere are situations when it is useful to control your application's `date` and `time` in order to override its behavior or avoid slow tests.\n\nWith [cy.clock()](/llm/markdown/api/commands/clock.md) you can control:\n\n*   `Date`\n*   `setTimeout`\n*   `setInterval`\n\n#### Common Scenarios\n\n##### Control `setInterval`\n\n*   You're polling something in your application with `setInterval` and want to control that.\n*   You have **throttled** or **debounced** functions which you want to control.\n\nOnce you've enabled [`cy.clock()`](/llm/markdown/api/commands/clock.md) you can control time by **ticking** it ahead by milliseconds.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)\n```\n\nYou can call [`cy.clock()`](/llm/markdown/api/commands/clock.md) **prior** to visiting your application and we will automatically bind it to the application on the next [`cy.visit()`](/llm/markdown/api/commands/visit.md). The same concept applies to mounting a component with [`cy.mount()`](/llm/markdown/api/commands/mount.md). We bind **before** any timers from your code can be invoked.\n\n##### Restore the clock\n\nYou can restore the clock and allow your application to resume normally without manipulating native global functions related to time. This is automatically called between tests.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)// more test code here// restore the clockcy.clock().then((clock) => {  clock.restore()})// more test code here\n```\n\nYou could also restore by using [.invoke()](/llm/markdown/api/commands/invoke.md) to invoke the `restore` function.\n\n```\ncy.clock().invoke('restore')\n```\n",
      "section": "app",
      "anchors": [
        "clock"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 257
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#common-scenarios",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Common Scenarios",
      "heading_level": 4,
      "content_markdown": "#### Common Scenarios\n\n##### Control `setInterval`\n\n*   You're polling something in your application with `setInterval` and want to control that.\n*   You have **throttled** or **debounced** functions which you want to control.\n\nOnce you've enabled [`cy.clock()`](/llm/markdown/api/commands/clock.md) you can control time by **ticking** it ahead by milliseconds.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)\n```\n\nYou can call [`cy.clock()`](/llm/markdown/api/commands/clock.md) **prior** to visiting your application and we will automatically bind it to the application on the next [`cy.visit()`](/llm/markdown/api/commands/visit.md). The same concept applies to mounting a component with [`cy.mount()`](/llm/markdown/api/commands/mount.md). We bind **before** any timers from your code can be invoked.\n\n##### Restore the clock\n\nYou can restore the clock and allow your application to resume normally without manipulating native global functions related to time. This is automatically called between tests.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)// more test code here// restore the clockcy.clock().then((clock) => {  clock.restore()})// more test code here\n```\n\nYou could also restore by using [.invoke()](/llm/markdown/api/commands/invoke.md) to invoke the `restore` function.\n\n```\ncy.clock().invoke('restore')\n```\n",
      "section": "app",
      "anchors": [
        "common-scenarios"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 208
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#control-setinterval",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Control setInterval",
      "heading_level": 5,
      "content_markdown": "##### Control `setInterval`\n\n*   You're polling something in your application with `setInterval` and want to control that.\n*   You have **throttled** or **debounced** functions which you want to control.\n\nOnce you've enabled [`cy.clock()`](/llm/markdown/api/commands/clock.md) you can control time by **ticking** it ahead by milliseconds.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)\n```\n\nYou can call [`cy.clock()`](/llm/markdown/api/commands/clock.md) **prior** to visiting your application and we will automatically bind it to the application on the next [`cy.visit()`](/llm/markdown/api/commands/visit.md). The same concept applies to mounting a component with [`cy.mount()`](/llm/markdown/api/commands/mount.md). We bind **before** any timers from your code can be invoked.\n",
      "section": "app",
      "anchors": [
        "control-setinterval"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 120
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#restore-the-clock",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Restore the clock",
      "heading_level": 5,
      "content_markdown": "##### Restore the clock\n\nYou can restore the clock and allow your application to resume normally without manipulating native global functions related to time. This is automatically called between tests.\n\n```\ncy.clock()cy.visit('http://localhost:3333')cy.get('#search').type('Acme Company')cy.tick(1000)// more test code here// restore the clockcy.clock().then((clock) => {  clock.restore()})// more test code here\n```\n\nYou could also restore by using [.invoke()](/llm/markdown/api/commands/invoke.md) to invoke the `restore` function.\n\n```\ncy.clock().invoke('restore')\n```\n",
      "section": "app",
      "anchors": [
        "restore-the-clock"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 84
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#assertions",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Assertions",
      "heading_level": 3,
      "content_markdown": "### Assertions\n\nOnce you have a `stub` or a `spy` in hand, you can then create assertions about them.\n\n```\nconst user = {  getName: (arg) => {    return arg  },  updateEmail: (arg) => {    return arg  },  fail: () => {    throw new Error('fail whale')  },}// force user.getName() to return \"Jane\"cy.stub(user, 'getName').returns('Jane Lane')// spy on updateEmail but do not change its behaviorcy.spy(user, 'updateEmail')// spy on fail but do not change its behaviorcy.spy(user, 'fail')// invoke getNameconst name = user.getName(123)// invoke updateEmailconst email = user.updateEmail('jane@devs.com')try {  // invoke fail  user.fail()} catch (e) {}expect(name).to.eq('Jane Lane') // trueexpect(user.getName).to.be.calledOnce // trueexpect(user.getName).not.to.be.calledTwice // trueexpect(user.getName).to.be.calledWith(123)expect(user.getName).to.be.calledWithExactly(123) // trueexpect(user.getName).to.be.calledOn(user) // trueexpect(email).to.eq('jane@devs.com') // trueexpect(user.updateEmail).to.be.calledWith('jane@devs.com') // trueexpect(user.updateEmail).to.have.returned('jane@devs.com') // trueexpect(user.fail).to.have.thrown('Error') // true\n```\n",
      "section": "app",
      "anchors": [
        "assertions"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 149
    },
    {
      "id": "app/guides/stubs-spies-and-clocks#integration-and-extensions",
      "doc_id": "app/guides/stubs-spies-and-clocks",
      "heading": "Integration and Extensions",
      "heading_level": 2,
      "content_markdown": "## Integration and Extensions\n\nBeyond integrating these tools together, we have also extended and improved collaboration between these tools.\n\n**Some examples:**\n\n*   We replaced Sinon's argument stringifier for a much less noisy, more performant, custom version.\n*   We improved the `sinon-chai` assertion output by changing what is displayed during a passing vs. failing test.\n*   We added aliasing support to `stub` and `spy` APIs.\n*   We automatically restore and tear down `stub`, `spy`, and `clock` between tests.\n\nWe also integrated all of these APIs directly into the Command Log, so you can visually see what's happening in your application.\n\nWe visually indicate when:\n\n*   A `stub` is called\n*   A `spy` is called\n*   A `clock` is ticked\n\nWhen you use aliasing with the [`.as()`](/llm/markdown/api/commands/as.md) command, we also correlate those aliases with the calls. This works identically to aliasing [`cy.intercept()`](/llm/markdown/api/commands/intercept.md).\n\nWhen stubs are created by calling the method `.withArgs(...)` we also visually link these together.\n\nWhen you click on a stub or spy, we also output **remarkably** helpful debugging information.\n\nFor instance we automatically display:\n\n*   The call count (and the total number of calls)\n*   The arguments, without transforming them (they are the real arguments)\n*   The return value of the function\n*   The context the function was invoked with\n",
      "section": "app",
      "anchors": [
        "integration-and-extensions"
      ],
      "path": "/llm/json/chunked/app/guides/stubs-spies-and-clocks.json",
      "token_estimate": 281
    }
  ]
}