Make Cypress End‑to‑End Tests Reliable with cy.intercept
Flaky network calls in Cypress tests? Use cy.intercept to mock, spy on, or modify HTTP traffic, turning flaky, data‑dependent checks into deterministic, fast tests. Learn how, when, and where to apply it effectively.
14 Oct 2025, 10:52 UTC

Concrete Problem: Flaky Network Calls in Cypress
When a Cypress test hits a live API, network latency, authentication changes, or backend outages can cause intermittent failures. Developers often add manual delays or duplicate backend logic to stabilize tests, which bloats the test suite and masks real integration issues.
Thesis: Use cy.intercept to Decouple UI Tests from the Backend
cy.intercept lets you mock, spy on, or modify HTTP traffic without touching the application code. When applied correctly it turns flaky, data‑dependent tests into deterministic, fast, and isolated checks.
What cy.intercept Brings to the Table
- Routing flexibility: match by URL, method, headers, or body.
- Dynamic responses: return fixtures, status codes, or programmatic data.
- Automatic cleanup: intercepts are cleared after each
itblock, preventing leakage. - Spy & wait capabilities:
cy.wait('@alias')lets you assert on request payloads or timing.
How to Wire an Intercept in a Test
Below is a minimal example that replaces a real API call with a local fixture. The test visits a page that fetches /api/users and renders the list.
// cypress/integration/user_list.spec.js
describe('User list page', () => {
it('renders mocked users', () => {
// 1. Set up the intercept before the page loads
cy.intercept('GET', '/api/users', {
statusCode: 200,
body: { users: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }] }
}).as('getUsers');
// 2. Visit the page – the intercept will fire on the fetch
cy.visit('/users');
// 3. Wait for the mocked request to finish (optional but guarantees ordering)
cy.wait('@getUsers');
// 4. Assert that the UI displays the mocked data
cy.get('.user-item').should('have.length', 2);
cy.contains('.user-item', 'Alice');
cy.contains('.user-item', 'Bob');
});
});
Run this test twice in a row. Because cy.intercept instances are automatically cleared between it blocks, the second run does not inherit the first test’s intercept unless you chain it explicitly.
Trade‑Offs & Limitations
- Hiding integration bugs: If you mock every endpoint, the UI may never exercise real server logic. A failing integration can go unnoticed.
- Brittle matching: Using complex regex or deep body matching can break when the API evolves. Keep matchers simple and document their intent.
- State leakage: While intercepts clear automatically, aliasing them inside
beforeEachcan lead to stale references if the test suite grows.
Practical Tips for Using cy.intercept Effectively
- Mock only the endpoints that are non‑critical to the test scenario.
- Use fixture files for static data; generate dynamic data inside the intercept callback when needed.
- Leverage
cy.wait('@alias')to assert on request payloads and timing. - Run a quick benchmark: compare test run times with and without intercepts to quantify the speed‑up.
- Keep intercept definitions close to the test that uses them for readability.
Verification Checklist
- Confirm that the UI shows the mocked data by inspecting the DOM.
- Run the test suite in CI and verify that network latency does not affect overall duration.
- Periodically run a “real‑API” test (no intercept) to surface any contract drift.
Actionable Closing
Adopting cy.intercept as a first‑class tool for network stubbing can dramatically increase test reliability and speed. Start by mocking the least critical endpoints, keep your matchers lean, and schedule occasional “real‑API” runs to guard against hidden integration failures. With these practices, your Cypress suite will be both fast and trustworthy.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.