Stubbing API Calls in Cypress Tests with cy.intercept
Learn how to use Cypress.io's cy.intercept to stub API calls, create deterministic UI tests, and avoid backend‑induced flakiness while understanding the trade‑offs.
22 Mar 2026, 00:36 UTC

Problem: Flaky UI Tests Caused by a Changing Backend
When a frontend test makes real HTTP requests, any change in the API—new fields, different status codes, or latency—can cause the test to fail even though the UI code is correct. This makes the test suite slow to trust and forces developers to constantly chase backend drift.
Thesis: cy.intercept Gives Deterministic, Isolated Tests Without Touching Application Code
Cypress’s built‑in network stubbing lets you replace or observe outgoing requests directly in the test file. The stub runs inside Cypress, so the browser never contacts the real server, yet the application receives a response that looks exactly like the real one. Because the intercept participates in Cypress’s automatic waiting and retry‑ability, assertions on the intercepted route are as resilient as DOM commands.
Section 1: Basic Stub with a Fixture
Start by adding a JSON fixture that represents the payload you want the UI to see. Suppose the application fetches a list of users from /api/users and renders them in a table.
// cypress/fixtures/users.json
[
{ "id": 1, "name": "Ada Lovelace" },
{ "id": 2, "name": "Grace Hopper" }
]
In the test, use cy.intercept to match the GET request and return the fixture.
// cypress/e2e/users-list.cy.js
describe('Users page', () => {
it('renders the stubbed user list', () => {
// Stub the request before visiting the page
cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers');
cy.visit('/users');
// Wait for the intercepted request to resolve (optional but shows intent)
cy.wait('@getUsers');
// Assert the UI reflects the fixture data
cy.get('table tbody tr').should('have.length', 2);
cy.get('table tbody tr').eq(0).should('contain', 'Ada Lovelace');
cy.get('table tbody tr').eq(1).should('contain', 'Grace Hopper');
});
});
When you run npx cypress open and execute this test, the Network tab in DevTools shows no call to /api/users; the UI is populated solely from the stubbed fixture.
Section 2: Dynamic Responses and Alias‑Based Waiting
Sometimes you need the response to depend on the request (e.g., query parameters, headers, or body). Cypress lets you provide a callback function that receives the request object and returns a response.
cy.intercept('GET', '/api/users', (req) => {
const limit = req.query.limit ?? 10;
const fakeUsers = Array.from({ length: limit }, (_, i) => ({
id: i + 1,
name: `User ${i + 1}`
}));
req.reply({ statusCode: 200, body: fakeUsers });
}).as('dynamicUsers');
You can then wait for the alias @dynamicUsers with cy.wait and assert on the request that was sent (e.g., verify that a specific header was present). This keeps the test synchronized with asynchronous UI updates while still avoiding the real backend.
Section 3: Trade‑Offs and Limitations
While stubbing eliminates flakiness, it also hides contract mismatches between frontend and backend. A test may pass with a stub that returns a field the real API no longer provides, leading to surprises in production. To mitigate this risk:
- Run occasional contract tests against a staging or mock server that mirrors the production contract.
- Keep intercept patterns simple (exact URL and method) and document why each stub exists.
- Prefer fixtures for static data and reserve callbacks for cases where you truly need to inspect the request.
Over‑using complex regex or body predicates can make the test file hard to read and maintain. Treat intercepts as you would any other test utility: clear, concise, and reviewed.
Actionable Closing: Add a Lightweight Contract Check
In your CI pipeline, keep the fast, stubbed unit‑style tests for every pull request. Additionally, schedule a nightly job that runs a small suite against a deployed staging environment with cy.intercept removed (or set to false) to validate that the real API still matches the expectations encoded in your fixtures. This combination gives you the speed of isolated tests and the safety of occasional contract verification.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.