Bird
Raised Fist0
Cypresstesting~15 mins

Stubbing responses in Cypress - Deep Dive

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of stubbing responses in Cypress testing?
easy
A. To fake server responses so tests run without a real backend
B. To speed up the browser rendering process
C. To automatically generate test data
D. To record user interactions for playback

Solution

  1. Step 1: Understand stubbing concept

    Stubbing means faking server responses so the app can be tested without a real backend.
  2. Step 2: Identify purpose in Cypress

    Cypress uses stubbing to isolate frontend tests from backend dependencies, making tests faster and more reliable.
  3. Final Answer:

    To fake server responses so tests run without a real backend -> Option A
  4. Quick Check:

    Stubbing = Fake server response [OK]
Hint: Stubbing fakes backend responses for isolated frontend tests [OK]
Common Mistakes:
  • Thinking stubbing speeds up browser rendering
  • Confusing stubbing with test data generation
  • Believing stubbing records user actions
2. Which of the following is the correct syntax to stub a GET request to '/api/data' with Cypress?
easy
A. cy.stub('GET', '/api/data', { fixture: 'data.json' })
B. cy.route('GET', '/api/data', { fixture: 'data.json' })
C. cy.intercept('GET', '/api/data', { fixture: 'data.json' })
D. cy.mock('GET', '/api/data', { fixture: 'data.json' })

Solution

  1. Step 1: Identify correct Cypress command

    The current Cypress command to stub network requests is cy.intercept().
  2. Step 2: Check method and parameters

    Using cy.intercept('GET', '/api/data', { fixture: 'data.json' }) correctly stubs a GET request with a fixture response.
  3. Final Answer:

    cy.intercept('GET', '/api/data', { fixture: 'data.json' }) -> Option C
  4. Quick Check:

    Use cy.intercept for stubbing requests [OK]
Hint: Use cy.intercept for stubbing, not cy.stub or cy.route [OK]
Common Mistakes:
  • Using cy.stub instead of cy.intercept
  • Using deprecated cy.route command
  • Using cy.mock which does not exist in Cypress
3. Given the code below, what will be the output of the test assertion?
cy.intercept('GET', '/users', { body: [{ id: 1, name: 'Alice' }] }).as('getUsers');
cy.visit('/users');
cy.wait('@getUsers').its('response.body[0].name').should('equal', 'Alice');
medium
A. Test passes because the stubbed response matches 'Alice'
B. Test fails because the alias '@getUsers' is not defined
C. Test fails because the response body is empty
D. Test throws a syntax error due to incorrect intercept usage

Solution

  1. Step 1: Analyze the intercept stub

    The intercept stubs a GET request to '/users' with a response body containing one user named 'Alice'.
  2. Step 2: Check the wait and assertion

    The test waits for '@getUsers' and asserts the first user's name equals 'Alice', which matches the stub.
  3. Final Answer:

    Test passes because the stubbed response matches 'Alice' -> Option A
  4. Quick Check:

    Stub response matches assertion = pass [OK]
Hint: Alias stub and assert matching response for pass [OK]
Common Mistakes:
  • Assuming alias is undefined without .as()
  • Thinking response body is empty
  • Confusing syntax of cy.intercept
4. Identify the error in the following Cypress stub code:
cy.intercept('POST', '/login', { statusCode: 200, body: { token: 'abc123' } });
cy.visit('/login');
cy.wait('@loginRequest');
medium
A. cy.visit must come before cy.intercept
B. The HTTP method 'POST' is invalid in cy.intercept
C. The response body must be a string, not an object
D. The alias '@loginRequest' is missing because the intercept was not aliased

Solution

  1. Step 1: Check alias usage

    The intercept is defined but not given an alias using .as(), so '@loginRequest' does not exist.
  2. Step 2: Understand wait on alias

    Waiting on '@loginRequest' fails because the alias was never created.
  3. Final Answer:

    The alias '@loginRequest' is missing because the intercept was not aliased -> Option D
  4. Quick Check:

    Alias missing causes wait failure [OK]
Hint: Always alias intercept with .as() before waiting [OK]
Common Mistakes:
  • Forgetting to add .as() to intercept
  • Thinking POST is invalid method
  • Believing response body must be string
5. You want to stub a GET request to '/products' that returns different responses based on a query parameter 'category'. Which is the best way to implement this in Cypress?
hard
A. Create multiple cy.intercept calls with the same URL but different responses
B. Use cy.intercept with a function handler to check req.query.category and send different responses
C. Use cy.intercept with a static response ignoring query parameters
D. Use cy.route with a fixture file for all categories

Solution

  1. Step 1: Understand dynamic stubbing need

    Different responses based on query parameters require conditional logic in the stub.
  2. Step 2: Use function handler in cy.intercept

    cy.intercept supports a function to inspect the request and send custom responses based on req.query.category.
  3. Final Answer:

    Use cy.intercept with a function handler to check req.query.category and send different responses -> Option B
  4. Quick Check:

    Function handler enables dynamic stubbing [OK]
Hint: Use function in cy.intercept for dynamic responses [OK]
Common Mistakes:
  • Trying multiple intercepts with same URL (only last applies)
  • Ignoring query parameters in stub
  • Using deprecated cy.route instead of cy.intercept
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard