Stubbing API Responses with Cypress intercept() to Eliminate Backend Flakiness
Learn how to use cy.intercept() to stub API responses in Cypress, eliminating backend flakiness and enabling the testing of edge cases like 500 errors and empty states.
21 Nov 2025, 19:05 UTC

The Problem: Unstable Tests Due to Backend Dependencies
End-to-end (E2E) tests often fail not because of UI bugs, but because of unstable staging environments, slow API responses, or data that changes between test runs. Relying on a live backend for every test case introduces non-deterministic results (flakiness) and increases test execution time.
The solution is network stubbing using cy.intercept(). By intercepting HTTP requests and providing a predefined response, you decouple the frontend tests from the backend state, allowing you to simulate edge cases—like 500 Internal Server Errors or empty data sets—that are difficult to trigger manually in a live environment.
Prerequisites
- Cypress installed and configured (Version 6.0+ required;
cy.intercept()replaces the deprecatedcy.route()). - A basic understanding of the application's API endpoints and the expected JSON response structures.
- Administrative access to the test suite files to modify
cypress/e2eorcypress/support/e.js.
Implementing Network Stubs
To stub a request, you must define the intercept before the action that triggers the network call. If the intercept is defined after the click or page load, the request will pass through to the real server.
Step 1: Define the Intercept and Alias
Use cy.intercept() to match the HTTP method and URL. Assign an alias using .as() so the test can explicitly wait for the request to complete.
// In your test file (.cy.js)
cy.intercept('GET', '/api/v1/user/profile', {
statusCode: 200,
body: {
id: '123',
username: 'test_user',
email: '[contact removed]'
}
}).as('getUserProfile');
Step 2: Trigger the Request and Wait
Perform the UI action that initiates the API call. Use cy.wait() to pause test execution until the intercepted request is resolved. This prevents the test from asserting against a loading state.
// Trigger the action
cy.visit('/profile');
// Wait for the stubbed response to be returned
cy.wait('@getUserProfile');
Step 3: Verify the UI State
Assert that the UI correctly renders the data provided in the stubbed response body.
// Check if the stubbed username appears in the DOM
cy.get('[data-testid="username-display"]').should('contain', 'test_user');
Handling Dynamic Scenarios and Errors
Stubbing is most powerful when testing failure states. You can simulate a server crash or a validation error by changing the statusCode.
| Scenario | Configuration | Expected UI Outcome |
|---|---|---|
| Server Error | statusCode: 500 |
Error toast or "Something went wrong" message. |
| Unauthorized | statusCode: 401 |
Redirect to /login page. |
| Empty State | body: [] |
"No items found" illustration/text. |
Example: Simulating a 403 Forbidden Error
cy.intercept('POST', '/api/v1/admin/settings', {
statusCode: 403,
body: { error: 'Insufficient permissions' }
}).as('updateSettingsFail');
cy.get('#save-settings').click();
cy.wait('@updateSettingsFail');
cy.get('.alert-danger').should('be.visible').and('contain', 'Insufficient permissions');
Diagnostic Checks and Limitations
To verify that your intercept is working as intended, check the Cypress Test Runner. In the Command Log (left sidebar), the intercept call will be listed. When the request occurs, you will see the alias (e.g., @getUserProfile) appear. Clicking it will show the request and response headers/body in the browser console.
Critical Limitations
- Contract Drift: Stubbing creates a "fake" version of your API. If the actual backend API changes its response structure but you don't update your stubs, tests will pass while the production app breaks.
- Wildcard Over-matching: Using
cy.intercept('GET', '**/api/**')may accidentally stub requests you intended to let pass through to the server. Be as specific as possible with URL paths. - Execution Order: Intercepts are processed in the order they are defined. If two intercepts match the same request, the last one defined takes precedence.
Rollback and State Reset
Cypress automatically clears all intercepts between tests. You do not need to manually "undo" a stub. However, if you define global intercepts in support/e.js, they will persist across all tests in the suite. To override a global stub for a specific test, simply define a new cy.intercept() within that specific it() block.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.