0
0
Cypresstesting~15 mins

Stubbing responses in Cypress - Deep Dive

Choose your learning style9 modes available
Overview - Stubbing responses
What is it?
Stubbing responses means faking the data a web app gets from a server during testing. Instead of calling the real server, the test gives back prepared answers. This helps test how the app behaves with different server replies without waiting or relying on the real server. It makes tests faster and more reliable.
Why it matters
Without stubbing, tests depend on real servers that can be slow, change data, or be offline. This causes tests to fail for reasons unrelated to the app's code. Stubbing ensures tests run quickly and always get the expected data, so developers can trust test results and fix real problems faster.
Where it fits
Before learning stubbing, you should understand basic Cypress test writing and how web apps communicate with servers using HTTP requests. After mastering stubbing, you can learn about spying on requests, mocking complex APIs, and testing error handling in apps.
Mental Model
Core Idea
Stubbing responses means replacing real server answers with fake ones during tests to control and speed up testing.
Think of it like...
It's like pretending to be a waiter in a restaurant test: instead of waiting for the kitchen to cook, you quickly hand over a fake dish to see how the customer reacts.
┌───────────────┐       ┌───────────────┐
│  Web App     │──────▶│  Server       │
└───────────────┘       └───────────────┘
       ▲                       ▲
       │                       │
       │      Stubbed Response │
       └───────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding HTTP Requests in Tests
🤔
Concept: Tests can watch and control the HTTP requests a web app makes to servers.
When a web app loads data, it sends HTTP requests to a server. Cypress can listen to these requests during tests to check what the app asks for and what it gets back.
Result
You know how to detect when the app asks for data and see the real server's response.
Understanding HTTP requests is key because stubbing works by intercepting these requests and changing their responses.
2
FoundationWhat is Stubbing Responses?
🤔
Concept: Stubbing means giving fake answers to HTTP requests during tests instead of real server data.
In Cypress, you can tell the test to catch a request and reply with your own data. This stops the app from calling the real server and uses your prepared response instead.
Result
Tests run faster and don't depend on the real server's state or speed.
Knowing stubbing lets you control test conditions exactly, making tests more stable and predictable.
3
IntermediateUsing cy.intercept() to Stub Responses
🤔Before reading on: do you think cy.intercept() can stub any HTTP method or only GET? Commit to your answer.
Concept: Cypress uses cy.intercept() to catch and stub HTTP requests of any method like GET, POST, PUT, DELETE.
Example: cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers') This tells Cypress to catch GET requests to '/api/users' and respond with data from 'users.json' file instead of the real server.
Result
When the app asks for users, it gets the fake data from 'users.json' immediately.
Knowing cy.intercept() works for all HTTP methods lets you stub any server interaction your app makes.
4
IntermediateStubbing Dynamic Responses with Functions
🤔Before reading on: do you think stub responses can be static only, or can they change based on the request? Commit to your answer.
Concept: You can provide a function to cy.intercept() to create responses that change depending on the request details.
Example: cy.intercept('GET', '/api/users/*', (req) => { const userId = req.url.split('/').pop() req.reply({ id: userId, name: `User ${userId}` }) }).as('getUser') This stubs responses for any user ID dynamically.
Result
The app gets a custom user object matching the requested ID every time.
Dynamic stubbing lets tests cover many cases without writing many static files.
5
IntermediateWaiting for Stubbed Requests to Complete
🤔
Concept: You can wait for stubbed requests to finish before checking app behavior to avoid timing issues.
Example: cy.intercept('POST', '/api/login', { statusCode: 200 }).as('login') cy.get('button.login').click() cy.wait('@login') cy.get('.welcome').should('be.visible') Waiting ensures the app finished processing the stubbed response before assertions.
Result
Tests become more reliable and avoid false failures due to timing.
Waiting for stubbed requests prevents flaky tests caused by asynchronous delays.
6
AdvancedStubbing Error and Edge Case Responses
🤔Before reading on: do you think stubbing can simulate server errors like 500 or 404? Commit to your answer.
Concept: Stubbing can simulate server errors or slow responses to test app error handling and loading states.
Example: cy.intercept('GET', '/api/data', { statusCode: 500, body: { error: 'Server error' } }).as('getDataError') This tests how the app reacts when the server fails.
Result
You can verify the app shows error messages or retries correctly.
Testing error cases with stubbing ensures your app handles real-world problems gracefully.
7
ExpertCombining Multiple Stubs and Network Conditions
🤔Before reading on: do you think multiple stubs can be active at once, or only one at a time? Commit to your answer.
Concept: You can use many stubs together and simulate network delays or failures to test complex app flows.
Example: cy.intercept('GET', '/api/users', { fixture: 'users.json', delayMs: 500 }).as('getUsers') cy.intercept('POST', '/api/login', { statusCode: 401 }).as('loginFail') This tests how the app behaves with slow data and failed login simultaneously.
Result
Tests cover realistic scenarios with multiple server behaviors and timing.
Combining stubs and delays helps catch bugs that only appear under complex network conditions.
Under the Hood
Cypress runs inside the browser and hooks into the network layer. When cy.intercept() is used, Cypress intercepts outgoing HTTP requests before they leave the browser. It then blocks the real request and sends back the stubbed response immediately. This interception happens using the browser's built-in APIs and Cypress's own code that overrides the network calls.
Why designed this way?
This design avoids needing a separate proxy server and keeps tests fast and reliable. Earlier tools used external proxies which were slower and harder to maintain. Cypress's in-browser interception allows seamless control over requests and responses with minimal setup.
┌───────────────┐
│  Web App     │
└──────┬────────┘
       │ HTTP Request
       ▼
┌───────────────┐
│ Cypress Hook  │
│ intercepts   │
│ request      │
└──────┬────────┘
       │
       │ Stubbed Response
       ▼
┌───────────────┐
│  Web App      │
│ receives fake │
│ response     │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does stubbing responses mean the real server is contacted at all? Commit to yes or no.
Common Belief:Stubbing responses still calls the real server but just modifies the data returned.
Tap to reveal reality
Reality:Stubbing completely blocks the real server call and sends back fake data instead.
Why it matters:Believing the server is contacted can lead to flaky tests that depend on server state or network issues.
Quick: Can stubbing only be used for GET requests? Commit to yes or no.
Common Belief:Stubbing only works for GET requests because other methods change data and are harder to fake.
Tap to reveal reality
Reality:Stubbing works for all HTTP methods including POST, PUT, DELETE, PATCH.
Why it matters:Limiting stubbing to GET prevents testing important app behaviors like form submissions or updates.
Quick: Does stubbing responses guarantee tests are always correct? Commit to yes or no.
Common Belief:If you stub responses, your tests are always reliable and correct.
Tap to reveal reality
Reality:Stubbing can hide real server bugs or mismatches if the fake data doesn't match real server behavior.
Why it matters:Over-relying on stubs without real integration tests can cause bugs to slip into production.
Quick: Can you stub multiple requests at the same time? Commit to yes or no.
Common Belief:You can only stub one request at a time in a test.
Tap to reveal reality
Reality:You can stub many requests simultaneously, each with different URLs and methods.
Why it matters:Thinking you can stub only one limits test coverage and realistic scenario simulation.
Expert Zone
1
Stubs can be conditionally applied only for certain test runs or environments to avoid interfering with real API tests.
2
Using fixtures for stub data helps keep tests clean but requires keeping fixture files updated with real API changes.
3
Delays and throttling in stubs simulate real network conditions but can make tests slower if overused.
When NOT to use
Stubbing is not suitable when you need to test real server integration, database changes, or end-to-end flows involving multiple systems. In those cases, use real API calls or dedicated integration tests.
Production Patterns
In real projects, stubbing is used to isolate frontend tests from backend instability, test error handling by simulating server failures, and speed up CI pipelines by avoiding slow network calls.
Connections
Mocking in Unit Testing
Stubbing responses in Cypress is a form of mocking, where dependencies are replaced with controlled fakes.
Understanding mocking in unit tests helps grasp how stubbing controls external dependencies in integration tests.
Network Proxy Servers
Stubbing replaces the need for external proxy servers that intercept and modify network traffic.
Knowing how proxies work clarifies why Cypress's in-browser interception is faster and simpler.
Theater Rehearsal
Stubbing is like actors rehearsing with stand-ins instead of the full cast to practice specific scenes.
This connection shows how isolating parts helps focus on testing specific behaviors without full dependencies.
Common Pitfalls
#1Not waiting for stubbed requests before assertions causes flaky tests.
Wrong approach:cy.intercept('GET', '/api/data', { fixture: 'data.json' }).as('getData') cy.get('.result').should('contain', 'Loaded')
Correct approach:cy.intercept('GET', '/api/data', { fixture: 'data.json' }).as('getData') cy.wait('@getData') cy.get('.result').should('contain', 'Loaded')
Root cause:The test checks UI before the stubbed response is processed, causing timing issues.
#2Using stale fixture data that doesn't match real API causes false positives.
Wrong approach:cy.intercept('GET', '/api/users', { fixture: 'oldUsers.json' })
Correct approach:Update 'oldUsers.json' regularly to match API changes or generate dynamic stub data.
Root cause:Ignoring API changes leads to tests passing with outdated data that doesn't reflect real behavior.
#3Stubbing only some requests but not others leads to inconsistent test environments.
Wrong approach:cy.intercept('GET', '/api/users', { fixture: 'users.json' }) // other requests go to real server
Correct approach:Stub all critical API calls or use a dedicated test server to avoid mixed real and fake data.
Root cause:Partial stubbing causes unpredictable test results due to mixed data sources.
Key Takeaways
Stubbing responses lets you replace real server data with fake data during tests to control app behavior.
Using cy.intercept() in Cypress, you can stub any HTTP request method with static or dynamic responses.
Waiting for stubbed requests to finish is essential to avoid flaky tests caused by timing issues.
Stubbing error responses helps test how your app handles failures and edge cases.
While stubbing improves test speed and reliability, it should be balanced with real integration tests to catch server-side bugs.