In this blog post, we'll look at how you can easily mock data from third party APIs using Cypress. Mocking has some advantages such as faster running of tests and enables your front end tests to be decoupled from any backend API.
The sample app that I will use for this tutorial is a react test app that I created recently from Stephen Grider's Modern React and Redux course. It's a simple image gallery search which uses unsplash API as its backend.
Cypress setup
To get started, let's run the following commands to install Cypress and set up initial structure.
npm i --save-dev cypress
npx cypress open
On the cypress/integration folder, delete the example spec files and add a new file called `image-search.spec.js`. Let's first write our tests without mocking any XHR requests.
The above spec file contains two scenarios. The first scenario verifies that images are not returned and the text "No content found" is displayed on our application if unsplash API does not return any available data while the second scenario verifies that the image gallery component is rendered and returns 10 images. However, with unsplash API, if you are on development mode, you are only limited to make 50 requests per hour to their API. Imagine if we hit that limit and we run our tests, the request call will fail which in turn will fail our tests.
Mocking XHR requests with Cypress
As we are only interested that our image component renders as expected, let's now write a test which mocks the XHR request to unsplash.
Our beforeEach hook is still the same code. Notice though that before I typed a search term, I made use of additional commands from Cypress which I will explain in detail below:
`cy.fixture('unsplash')` loads my mock data which I've called `unsplash.json` and is saved on my `cypress/fixtures` folder. This json file is basically an array of objects which contains my mock response for the unsplash API. I've also aliased this fixture as `@unsplashData` so I can reference this later.
`cy.server()` tells Cypress that we will be creating a mock server and will intercept any incoming network requests.
`cy.route('search/photos?query=mock+', '@unsplashData')` tells Cypress that for any route that matches our first parameter, we want this to return the `@unsplashData` fixtures.
To make sure that we have mocked the XHR request successfully, I've written an assertion which checks that the image description is set to "This is a mock data".
From the image below, you can also see that it has loaded our test fixtures correctly and our test passed. Notice as well that when we make a request to the unsplash API, it's marked with (XHR STUB) which is another visual indicator that we have successfully intercepted the network request.
Mocking data with Cypress is easy but this solution would only work for XHR requests. Requests using the Fetch API and other network requests like script tags are not currently intercepted. There's a lot of details and workarounds on how to mock these requests as reference here https://github.com/cypress-io/cypress/issues/95.
For the complete code reference, here is the link to my github repo. Hope this helps! 🙂
I haven't used it yet, but definitely something I want to try in my tests so I can test GUI without the need of constant requests to third party apps. Thanks Marie.