Understand Stub & Spy: APIs that will make your test better than ever on Cypress.io

Traitanit Huangsri
Cypress.io Thailand
5 min readAug 4, 2019

Hello everyone. Today I’m gonna talk about one of Cypress.io feature that will make your test better, less flaky tests. Yes, I’m talking about Stub & Spy APIs. Stub & Spy helping us to create some test scenario which we might think that is not automatable. But with Cypress.io, we can make that thing possible.

What’s are Stub & Spy? What’s difference between them ?

Stub

Stub is a way to simulate the behaviors of the application functions (or modules) that the tests are depend on. It’s mostly use for testing purpose. Instead of calling the real function, stub replace that one and return Canned Answers or some predefined object that we exactly know what will be returned. It’s commonly used in Unit Tests but can be used for End-to-End Tests with Cypress.io as well.

Spy

Spy is pretty much similar to Stub but not exactly the same. Spy does not change the behavior of application functions, it leaves them as it is but capture and record some information on how they’re called. For example to check if the function is called with correct parameters, to count number of times that function is invoked.

Stub & Spy on Cypress.io

We can simply create Stub and Spy on Cypress.io with APIs cy.stub and cy.spy I’m going to show you some examples in this article on how to use Stub and Spy in some interesting use cases.

// to define stub
cy.stub(object, 'functionName', 'stubFunction')
// to define spy
cy.spy(object, 'functionName', 'spyFunction')

Cypress adopted Stub and Spy object from Sinon.js that means we can reference all of usage from the official Sinon.js document. You can find more detail about Sinon Stub & Spy document below.

Sinon.js Stub: https://sinonjs.org/releases/latest/stubs/
Sinon.js Spy: https://sinonjs.org/releases/latest/spies/

Example#1: Prevent External URL Navigation

We usually found some web application that trying to navigate outside of the app e.g. external web, URL scheme like tel:// , mailto:// or even mobile app custom URL scheme like fb:// , myapp://

Click to make a phone call (tel://)
Test failed because of external URL navigation

I believe most of you might have seen some app that trying to navigate outside after clicking the button. This is pretty hard to create a test for this scenario because Cypress does not allow us to navigate outside the app (which is good because we should focus on testing our app not testing a browser navigation, right?) In this case, we have to use the Stub API to make our test possible.

Normally, Web Developer often uses window.location.href for any navigation outside the app. location.href is a property of native Window object. Unfortunately, we cannot stub the property of the object so we have to wrap it as a function and assign it as a custom Window function. Here is how can we stub the window.location.href property.

Then we create the test for this scenario by calling cy.window() to get the Window object and then stub the setLocationHref function with our stub function.

I stub the setLocationHref function with the winSetLocationHrefStub function. Then I can check whether the function is called with a correct parameter or not.

Test runs smoothly with Stubbed function

Example#2: Stubbing Window Prompt

Another example for Stub API. You might have seen the window.prompt() dialog that waits for user to input some text to the dialog. It’s pretty hard to create a test for this scenario as well. So Stubbing is a way to go to solve this problem.

window.prompt() waits for user input

When start writing test, I just create a stub for window.prompt() and return my Canned Answer back to the app. Please note that Cypress will reset and restore your stub after tests run automatically. So our stub will run in isolation which is pretty good :)

You can alias the Stub object as any name you want using as command. You can call cy.get() command to reference your stub and make an assertion with it.

No More window.prompt() dialog

Example#3 Spying Window Confirm Dialog

The last example of this article. I’m going to Spy the function window.confirm() to check if it is called once and also check the confirm message.

In this example, The confirm dialog is appear after user click the button. If user click ok, then the message “Yes, you’re hungry” will be displayed. Otherwise the message will be “No, you’re full.”. It’s simple, right? So I create a test with a Spy object to check if the function window.confirm() is called like this.

You can use Sinon-Chai Assertion for any Spy object. There are many assertions support for Spy object which you can see more detail here. In this case, I use should(‘be.calledOnce’) to check number of time that the window.confirm() function is called.

In my test code, I bind the event window:confirm to an anonymous function that return true as a result. That means the same output as user pressing ok button on confirm dialog. Here is the result of my test.

Spying window.confirm() function to check number of function calls.

These are just only 3 simple examples that you can apply Stub & Spy to fulfill your Cypress.io tests. There are many interesting use cases that you can use Stub & Spy to make your test better. Please see more examples here https://docs.cypress.io/guides/guides/stubs-spies-and-clocks.html

You can find all of my example code in my personal Github below.

Hope this article is useful for you. Happy Testing!

--

--