Using Cypress.io cy.intercept to Stub Network Requests Reliably
Learn how to use Cypress.io's cy.intercept to stub network requests, isolate frontend tests, and avoid flaky CI builds.
30 Aug 2026, 14:51 UTC

The Problem: Flaky Tests Due to Real API Calls
When end‑to‑end tests hit a real backend, they become dependent on network availability, data state, and latency. A temporary outage or a change in the API contract can cause a test to fail even though the frontend code works correctly.
Why cy.intercept Solves It
Cypress provides cy.intercept as a unified way to stub, mock, or spy on network requests. It replaces the older cy.route API and lets you define exactly which calls to intercept, what to return, and even how to delay them. Because the interception lives inside the test runner, changes take effect instantly and are cleared automatically after each test unless you preserve them.
A Worked Example: Stubbing a User List Endpoint
Suppose your application shows a list of users fetched from GET /api/users. You want the test to run offline and display a known set of names.
// cypress/e2e/user-list.cy.js
describe('User list page', () => {
beforeEach(() => {
// Intercept the GET request to /api/users and return a fixture
cy.intercept('GET', '/api/users', { fixture: 'users.json' })
.as('getUsers'); // alias for optional waiting
});
it('displays the mocked users', () => {
cy.visit('/users'); // adjust to your app's route
// Wait for the intercepted request (optional)
cy.wait('@getUsers');
// Verify the UI renders the names from the fixture
cy.get('.user-item').should('have.length', 3);
cy.get('.user-item').eq(0).should('contain', 'Ada Lovelace');
cy.get('.user-item').eq(1).should('contain', 'Grace Hopper');
cy.get('.user-item').eq(2).should('contain', 'Alan Turing');
});
});
Place a file cypress/fixtures/users.json with the following content:
[
{ "id": 1, "name": "Ada Lovelace" },
{ "id": 2, "name": "Grace Hopper" },
{ "id": 3, "name": "Alan Turing" }
]
When the test runs, Cypress prevents the actual network call, returns the JSON from the fixture, and the page renders the three names. You can confirm the interception succeeded by opening the Cypress Command Log and seeing the request marked as “(stubbed)”.
Trade‑offs and Limitations
- Selective stubbing is essential. Intercepting every request can hide genuine network errors and increase memory usage because each intercepted call creates a stub object.
- Dynamic response functions must be deterministic. If you generate the response based on a mutable variable (e.g., a counter), tests may become flaky unless you reset that variable in
beforeEach. - Large fixtures affect startup time. Loading a multi‑megabyte JSON file adds to the test’s initial load; consider splitting data or loading it lazily inside the intercept function.
- Interceptor scope. By default, interceptors defined in a
beforeEachare cleared after each test. If you need the same stub across several tests, either repeat the definition or usecy.intercept(..., { preserveSession: true })(available in recent Cypress versions) with caution.
Putting It Into Practice
Start small: pick one endpoint that your component depends on, add a cy.intercept line in a beforeEach hook, and verify the UI behaves as expected. Once the stub works, expand to other endpoints or add delay options to test loading states. Keep the intercepts as narrow as possible, and periodically review the Command Log to ensure you are not unintentionally stubbing calls you meant to test against the real server.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.