- Which libraries Cypress includes to provide typical testing functionality
- How to use stubs for asserting that code was called but preventing it from executing
- How to use spies for asserting that code was called without interfering with its execution
- How to control time for deterministically testing code that is time-dependent
- How Cypress improves and extends the included libraries
Cypress comes built in with the ability to stub and spy with
cy.spy() or modify your application’s time with
cy.clock() - which lets you manipulate
setInterval, amongst others.
These commands are useful when writing both unit tests and integration tests.
Cypress automatically bundles and wraps these libraries:
|Name||What it does|
You can refer to each of these libraries’ documentation for more examples and explanations.
A stub is a way to modify a function and delegate control overs its behavior to you (the programmer).
A stub is most commonly used in a unit test but is still useful during some integration/e2e tests.
// create a standalone stub (generally for use in unit test) cy.stub() // replace obj.method() with a stubbed function cy.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 error cy.stub(obj, 'method').rejects(new Error('foo'))
You generally stub a function when it has side effects you are trying to control.
- 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.locationand don’t want your application to be navigated.
- You’re trying to test your application’s “failure path” by forcing things to fail.
- You’re trying to test your application’s “happy path” by forcing things to pass.
- You want to “trick” your application into thinking it’s logged in or logged out.
- You’re using
oauthand want to stub login methods.
A 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.
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).
There are situations when it is useful to control your application’s
time in order to override its behavior or avoid slow tests.
cy.clock()gives you the ability to control:
- You’re polling something in your application with
setIntervaland want to control that.
- You have throttled or debounced functions which you want to control.
Once you’ve enabled
cy.clock()you can control time by ticking it ahead by milliseconds.
cy.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(). We bind before any timers from your application can be invoked. This works identically to
Once you have a
spyin hand, you can then create assertions about them.
# Integration and Extensions
Beyond integrating these tools together, we have also extended and improved collaboration between these tools.
- We replaced Sinon’s argument stringifier for a much less noisy, more performant, custom version.
- We improved the
sinon-chaiassertion output by changing what is displayed during a passing vs. failing test.
- We added aliasing support to
- We automatically restore and tear down
We also integrated all of these APIs directly into the Command Log, so you can visually see what’s happening in your application.
We visually indicate when:
When you use aliasing with the
.as()command, we also correlate those aliases with the calls. This works identically to aliasing a
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 remarkably 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
# See also
- Spies, stubs and clocks examples
- Stub navigator API in end-to-end tests