Cypress · Browser testing end to end

How do you stub network responses for different UI states?

Mediumstubbingfixtureserror statesUpdated Oct 2026
Quiz this track

Short answer

Use cy.intercept with a fixture, inline body or a reply callback to force loading, empty, error and edge-case responses. Stub the boundary, and keep at least some tests against the real API.

Stubbing lets a test reach states that are slow, rare or hard to produce with real data. A loading state needs a delayed response, an empty state needs an empty list, and an error state needs a non-2xx status. Each one is a small intercept, not a special backend.

ts
cy.intercept("GET", "/api/invoices", {
  statusCode: 500,
  body: { message: "Billing service unavailable" },
}).as("getInvoices");

cy.visit("/invoices");
cy.wait("@getInvoices");
cy.get("[data-cy=error]")
  .should("contain", "Billing service unavailable");
A 500 response exercises the error branch without breaking the real service.

Stub patterns worth having

  • Empty: an empty array or an object with no items
  • Loading: use a delay in the reply to observe the skeleton
  • Error: a 4xx or 5xx with the shape the UI expects
  • Partial: one field missing or null to test defensive rendering
  • Slow: a bounded delay, not an arbitrary sleep in the test body
ts
cy.intercept("GET", "/api/invoices", (req) => {
  req.reply({
    delay: 1000,
    statusCode: 200,
    body: [],
  });
}).as("getInvoices");
The delay lives in the response, so the test can assert on both the loading state and the empty state.
Stubs are not proof that the real API contract still works. Keep a contract or integration test against the real service, or the suite may stay green after the backend changes.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1How do you test a loading state deterministically?
  2. 2How do you stub a 500 response?
  3. 3Why keep tests against the real API?
  4. 4How do you simulate a slow network?

Say it in the interview

I use cy.intercept to stub the response shape the component needs. For a loading state I add a delay in the reply, for an empty state I return an empty collection, and for an error I return the status and body the UI expects. I keep these stubs focused on the boundary. I also keep a smaller set of tests against the real API so a contract change does not slip through.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Cypress mock interview and get scored feedback on depth, clarity and confidence.