{"__v":0,"_id":"589802d77c5f330f0091073b","category":{"__v":16,"_id":"56954a95fe18811700c9bfdf","pages":["56954a97fe18811700c9c01d","56954a97fe18811700c9c01e","56954a97fe18811700c9c01f","56954a97fe18811700c9c020","56954a97fe18811700c9c021","56954a97fe18811700c9c022","56954a97fe18811700c9c023","56954a97fe18811700c9c024","56954a97fe18811700c9c025","56954a97fe18811700c9c026","56954a97fe18811700c9c027","56954a97fe18811700c9c028","56954a97fe18811700c9c029","5696cda524490c3700170a05","5697efe61c4dc8230054268e","5697efe72cf4060d004eaa75","56993ff47465970d00650b8f","56a7a155dfdabc0d000ae910","56a7a155b5d0920d0051cd81","56a7a1a6cf6d771700baeee3","56a7a1a63d33bc2100793d5d","56a7a23097e8b00d0096d209","56a7a230ea3e3417000df4b1","56a7a25acf6d771700baeee6","56a7a25a03f28c0d00a545bf","56a7a2b83d33bc2100793d60","56a7a2b8b5d0920d0051cd82","56b27fe42db51f0d0044e566"],"project":"568fde81b700ce0d002f4b43","version":"56954a94fe18811700c9bfda","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-01-09T16:40:53.584Z","from_sync":false,"order":4,"slug":"guides","title":"Guides"},"parentDoc":null,"project":"568fde81b700ce0d002f4b43","user":"568fffce769f210d0013258f","version":{"__v":6,"_id":"56954a94fe18811700c9bfda","project":"568fde81b700ce0d002f4b43","createdAt":"2016-01-12T18:48:52.007Z","releaseDate":"2016-01-12T18:48:52.007Z","categories":["56954a95fe18811700c9bfdb","56954a95fe18811700c9bfdc","56954a95fe18811700c9bfdd","56954a95fe18811700c9bfde","56954a95fe18811700c9bfdf","56954a95fe18811700c9bfe0","56954a95fe18811700c9bfe1","56954a95fe18811700c9bfe2","56954a95fe18811700c9bfe3","56954a95fe18811700c9bfe4","5695649fdcaf0d1700cb8721","5696c1168560a60d00e2c1d6","56a7a32e79395317007c1ad6","5898fc3eec49fb0f004c2663","589cc675ea37da23004e05e1"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"foo","version_clean":"0.0.0","version":"0.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2017-02-06T05:00:07.089Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"auth":"required","params":[],"url":""},"isReference":false,"order":7,"body":"# Contents\n\n- :fa-angle-right: [Capabilities](#section-capabilities)\n- :fa-angle-right: [Libraries and Tools](#section-libraries-and-tools)\n- :fa-angle-right: [Common Scenarios](#section-common-scenarios)\n  - [Stubs](#section-stubs)\n  - [Spies](#section-spies)\n  - [Clock](#section-clock)\n  - [Assertions](#section-assertions)\n- :fa-angle-right: [Integration and Extensions](#section-integration-and-extensions)\n\n***\n\n# Capabilities\n\nCypress comes built in with the ability to [`stub`](https://on.cypress.io/api/stub), [`spy`](https://on.cypress.io/api/spy) or modify your applications [`clock`](https://on.cypress.io/api/clock) - such as controlling `Date`, `setTimeout`, and `setInterval`.\n\nThese commands are useful when writing both **unit tests** and **integration tests**.\n\n***\n\n# 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 [`stub`](https://on.cypress.io/api/stub) and [`spy`](https://on.cypress.io/api/spy) API's |\n| [`lolex`](https://github.com/sinonjs/lolex) | provides the [`clock`](https://on.cypress.io/api/clock) and [`tick`](https://on.cypress.io/api/tick) API's |\n| [`sinon-as-promised`](https://github.com/bendrucker/sinon-as-promised) | makes it easy to stub `Promise` returning functions |\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\n***\n\n# Common Scenarios\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"[Check out our example recipe testing spying, stubbing and time](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/spy_stub_clock_spec.js)\",\n  \"title\": \"Example test!\"\n}\n[/block]\n\n## Stubs\n\nA stub is a way to modify a function and force its behavior to be controlled by 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[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// create a standalone stub (generally for use in unit test)\\ncy.stub()\\n\\n// replace obj.method() with a stubbed function\\ncy.stub(obj, \\\"method\\\")\\n\\n// force obj.method() to return \\\"foo\\\"\\ncy.stub(obj, \\\"method\\\").returns(\\\"foo\\\")\\n\\n// force obj.method() when called with \\\"bar\\\" argument to return \\\"foo\\\"\\ncy.stub(obj, \\\"method\\\").withArgs(\\\"bar\\\").returns(\\\"foo\\\")\\n\\n// force obj.method() to return a promise which resolves to \\\"foo\\\"\\ncy.stub(obj, \\\"method\\\").resolves(\\\"foo\\\")\\n\\n// force obj.method() to return a promise rejected with an error\\ncy.stub(obj, \\\"method\\\").rejects(new Error(\\\"foo\\\"))\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\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 applications \"failure path\" by forcing things to fail.\n- You're trying to test your applications \"happy path\" by forcing things to pass.\n- You want to \"trick\" your application into thinking its logged in or logged out.\n- You're using `oauth` and want to stub login methods.\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"[Read more about how to use cy.stub](https://on.cypress.io/api/stub)\",\n  \"title\": \"cy.stub()\"\n}\n[/block]\n\n***\n\n## Spies\n\nA spy gives you the ability to \"spy\" on a function, by being able to capture and then assert that the function was calling with the right arguments, or that the function was called a certain number of times, or even what the return value or 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[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.spy(obj, \\\"method\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"[Read more about how to use cy.spy](https://on.cypress.io/api/spy)\",\n  \"title\": \"cy.spy()\"\n}\n[/block]\n\n***\n\n## Clock\n\nThere are situations when it is useful to control your applications `date` and `time` in order to force its behavior or avoid slow tests.\n\n[`cy.clock`](https://on.cypress.io/api/clock) gives you the ability to control:\n\n- `Date`\n- `setTimeout`\n- `setInterval`\n\n**Common Scenarios:**\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`](https://on.cypress.io/api/clock) you can then control time by **ticking** it ahead by milliseconds.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .clock()\\n  .visit(\\\"http://localhost:3333\\\")\\n  .get(\\\"#search\\\").type(\\\"foobarbaz\\\")\\n  .tick(1000)\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[`cy.clock`](https://on.cypress.io/api/clock) is special in that it can be called **prior** to visiting your application, and we will automatically bind it to the application on the next [`cy.visit`](https://on.cypress.io/api/visit). We bind **before** any timers from your application can be invoked. This works identically to [`cy.server`](https://on.cypress.io/api/server) + [`cy.route`](https://on.cypress.io/api/route).\n\n***\n\n## Assertions\n\nOnce you have a `stub` or a `spy` in hand, you can then create assertions about them.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"const user = {\\n  getName: function(arg){\\n    return arg\\n  },\\n\\n  updateEmail: function(arg){\\n    return arg\\n  },\\n\\n  fail: function(){\\n    throw new Error(\\\"fail whale\\\")\\n  }\\n}\\n\\n// force user.getName() to return \\\"Jane\\\"\\ncy.stub(user, \\\"getName\\\").returns(\\\"Jane Lane\\\")\\n\\n// spy on updateEmail but do not change its behavior\\ncy.spy(user, \\\"updateEmail\\\")\\n\\n// spy on fail but do not change its behavior\\ncy.spy(user, \\\"fail\\\")\\n\\n// invoke getName\\nconst name  = user.getName(123)\\n\\n// invoke updateEmail\\nconst email = user.updateEmail(\\\"jane:::at:::devs.com\\\")\\n\\ntry {\\n  // invoke fail\\n  user.fail()\\n  } catch (e) {\\n\\n}\\n\\nexpect(name).to.eq(\\\"Jane Lane\\\")                            // true\\nexpect(user.getName).to.be.calledOnce                      // true\\nexpect(user.getName).not.to.be.calledTwice                 // true\\nexpect(user.getName).to.be.calledWith(123)\\nexpect(user.getName).to.be.calledWithExactly(123)          // true\\nexpect(user.getName).to.be.calledOn(user)                  // true\\n\\nexpect(email).to.eq(\\\"[email protected]\\\")                       // true\\nexpect(user.updateEmail).to.be.calledWith(\\\"[email protected]\\\") // true\\nexpect(user.updateEmail).to.have.returned(\\\"[email protected]\\\") // true\\n\\nexpect(user.fail).to.have.thrown(\\\"Error\\\")                  // true\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n# Integration and Extensions\n\nBeyond just integrating these tools together we have also extended and improved the collaboration of these tools.\n\nSome 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 displays during a passing vs failing test.\n- We've added aliasing support to `stub` and `spy` API's.\n- We automatically restore and teardown `stub`, `spy`, and `clock` between tests.\n\nWe also integrated all of these API's 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\n\nWhen you use aliasing with the [`.as(alias)`](https://on.cypress.io/api/as) command, we also coorelate those aliases with the calls. This works identically to aliasing a [`cy.route`](https://on.cypress.io/api/route).\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 **incredibly** helpful debugging information.\n\nFor instance we automatically display:\n\n- The call count (and 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","excerpt":"Learn about when and why to use stubs, spies, and control clock time","slug":"stubs-spies-clocks","type":"basic","title":"Stubs Spies and Clocks"}

Stubs Spies and Clocks

Learn about when and why to use stubs, spies, and control clock time

# Contents - :fa-angle-right: [Capabilities](#section-capabilities) - :fa-angle-right: [Libraries and Tools](#section-libraries-and-tools) - :fa-angle-right: [Common Scenarios](#section-common-scenarios) - [Stubs](#section-stubs) - [Spies](#section-spies) - [Clock](#section-clock) - [Assertions](#section-assertions) - :fa-angle-right: [Integration and Extensions](#section-integration-and-extensions) *** # Capabilities Cypress comes built in with the ability to [`stub`](https://on.cypress.io/api/stub), [`spy`](https://on.cypress.io/api/spy) or modify your applications [`clock`](https://on.cypress.io/api/clock) - such as controlling `Date`, `setTimeout`, and `setInterval`. These commands are useful when writing both **unit tests** and **integration tests**. *** # Libraries and Tools Cypress automatically bundles and wraps these libraries: | Name | What it does | | --- | ---- | | [`sinon`](http://sinonjs.org) | provides the [`stub`](https://on.cypress.io/api/stub) and [`spy`](https://on.cypress.io/api/spy) API's | | [`lolex`](https://github.com/sinonjs/lolex) | provides the [`clock`](https://on.cypress.io/api/clock) and [`tick`](https://on.cypress.io/api/tick) API's | | [`sinon-as-promised`](https://github.com/bendrucker/sinon-as-promised) | makes it easy to stub `Promise` returning functions | | [`sinon-chai`](https://github.com/domenic/sinon-chai) | adds `chai` assertions for stubs and spies | You can refer to each of these libraries documentation for more examples and explanations. *** # Common Scenarios [block:callout] { "type": "info", "body": "[Check out our example recipe testing spying, stubbing and time](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/spy_stub_clock_spec.js)", "title": "Example test!" } [/block] ## Stubs A stub is a way to modify a function and force its behavior to be controlled by you (the programmer). A stub is most commonly used in a unit test but is still useful during some integration / e2e tests. [block:code] { "codes": [ { "code": "// create a standalone stub (generally for use in unit test)\ncy.stub()\n\n// replace obj.method() with a stubbed function\ncy.stub(obj, \"method\")\n\n// force obj.method() to return \"foo\"\ncy.stub(obj, \"method\").returns(\"foo\")\n\n// force obj.method() when called with \"bar\" argument to return \"foo\"\ncy.stub(obj, \"method\").withArgs(\"bar\").returns(\"foo\")\n\n// force obj.method() to return a promise which resolves to \"foo\"\ncy.stub(obj, \"method\").resolves(\"foo\")\n\n// force obj.method() to return a promise rejected with an error\ncy.stub(obj, \"method\").rejects(new Error(\"foo\"))\n", "language": "javascript" } ] } [/block] You generally stub a function when it has side effects you are trying to control. **Common Scenarios:** - You have a function that accepts a callback, and want to invoke the callback. - Your function returns a `Promise`, and you want to automatically resolve or reject it. - You have a function that wraps `window.location` and don't want your application to be navigated. - You're trying to test your applications "failure path" by forcing things to fail. - You're trying to test your applications "happy path" by forcing things to pass. - You want to "trick" your application into thinking its logged in or logged out. - You're using `oauth` and want to stub login methods. [block:callout] { "type": "info", "body": "[Read more about how to use cy.stub](https://on.cypress.io/api/stub)", "title": "cy.stub()" } [/block] *** ## Spies A spy gives you the ability to "spy" on a function, by being able to capture and then assert that the function was calling with the right arguments, or that the function was called a certain number of times, or even what the return value or context the function was called with. A 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). [block:code] { "codes": [ { "code": "cy.spy(obj, \"method\")\n", "language": "javascript" } ] } [/block] [block:callout] { "type": "info", "body": "[Read more about how to use cy.spy](https://on.cypress.io/api/spy)", "title": "cy.spy()" } [/block] *** ## Clock There are situations when it is useful to control your applications `date` and `time` in order to force its behavior or avoid slow tests. [`cy.clock`](https://on.cypress.io/api/clock) gives you the ability to control: - `Date` - `setTimeout` - `setInterval` **Common Scenarios:** - You're polling something in your application with `setInterval` and want to control that. - You have **throttled** or **debounced** functions which you want to control. Once you've enabled [`cy.clock`](https://on.cypress.io/api/clock) you can then control time by **ticking** it ahead by milliseconds. [block:code] { "codes": [ { "code": "cy\n .clock()\n .visit(\"http://localhost:3333\")\n .get(\"#search\").type(\"foobarbaz\")\n .tick(1000)\n", "language": "javascript" } ] } [/block] [`cy.clock`](https://on.cypress.io/api/clock) is special in that it can be called **prior** to visiting your application, and we will automatically bind it to the application on the next [`cy.visit`](https://on.cypress.io/api/visit). We bind **before** any timers from your application can be invoked. This works identically to [`cy.server`](https://on.cypress.io/api/server) + [`cy.route`](https://on.cypress.io/api/route). *** ## Assertions Once you have a `stub` or a `spy` in hand, you can then create assertions about them. [block:code] { "codes": [ { "code": "const user = {\n getName: function(arg){\n return arg\n },\n\n updateEmail: function(arg){\n return arg\n },\n\n fail: function(){\n throw new Error(\"fail whale\")\n }\n}\n\n// force user.getName() to return \"Jane\"\ncy.stub(user, \"getName\").returns(\"Jane Lane\")\n\n// spy on updateEmail but do not change its behavior\ncy.spy(user, \"updateEmail\")\n\n// spy on fail but do not change its behavior\ncy.spy(user, \"fail\")\n\n// invoke getName\nconst name = user.getName(123)\n\n// invoke updateEmail\nconst email = user.updateEmail(\"[email protected]\")\n\ntry {\n // invoke fail\n user.fail()\n } catch (e) {\n\n}\n\nexpect(name).to.eq(\"Jane Lane\") // true\nexpect(user.getName).to.be.calledOnce // true\nexpect(user.getName).not.to.be.calledTwice // true\nexpect(user.getName).to.be.calledWith(123)\nexpect(user.getName).to.be.calledWithExactly(123) // true\nexpect(user.getName).to.be.calledOn(user) // true\n\nexpect(email).to.eq(\"[email protected]\") // true\nexpect(user.updateEmail).to.be.calledWith(\"[email protected]\") // true\nexpect(user.updateEmail).to.have.returned(\"[email protected]\") // true\n\nexpect(user.fail).to.have.thrown(\"Error\") // true\n", "language": "javascript" } ] } [/block] *** # Integration and Extensions Beyond just integrating these tools together we have also extended and improved the collaboration of these tools. Some examples: - We replaced Sinon's argument stringifier for a much less noisy, more performant, custom version. - We improved the `sinon-chai` assertion output by changing what displays during a passing vs failing test. - We've added aliasing support to `stub` and `spy` API's. - We automatically restore and teardown `stub`, `spy`, and `clock` between tests. We also integrated all of these API's directly into the Command Log so you can visually see what's happening in your application. We visually indicate when: - A `stub` is called - A `spy` is called - A `clock` is ticked When you use aliasing with the [`.as(alias)`](https://on.cypress.io/api/as) command, we also coorelate those aliases with the calls. This works identically to aliasing a [`cy.route`](https://on.cypress.io/api/route). When stubs are created by calling the method `.withArgs(...)` we also visually link these together. When you click on a stub or spy we also output **incredibly** helpful debugging information. For instance we automatically display: - The call count (and total number of calls) - The arguments without transforming them (they are the real arguments) - The return value of the function - The context the function was invoked with