## TL;DR

Use `cy.intercept()` to stub network responses the app fetches; use `cy.stub()` for direct function spies. Intercept tests the real request path; stub tests units in isolation.

## Error

```text
(Not an error; a technique choice. The confusion: both are called "stubbing".)
```

## Steps

1. If the code under test makes a real HTTP request, use `cy.intercept()` with a fixture or inline body. Expected: the app's fetch path exercised.
2. If testing a callback or method directly, use `cy.stub()` / `sinon.stub()`. Expected: unit-level control.
3. Do not stub what you can intercept: intercept keeps more of the real stack. Expected: higher-fidelity tests.
4. Do not intercept what should be a contract test: over-mocked e2e hides backend drift. Expected: a few unmocked paths remain.
5. Document which tests mock what in the test name or comment. Expected: future readers know the fidelity.

## When to use

- Deciding mock strategy for a test.
- Reviewing over-mocked suites.

## When not to use

- You need full-stack confidence (use real backend for some tests).
- Playwright (use page.route).

## Tool compatibility

- Cypress 10 through 14; `cy.intercept`, sinon stubs.

## Variant phrasings

### Cypress stub API response

Usually means intercept; use the network-level tool.

### cy.intercept vs cy.stub

The comparison; network vs function.

## Why it happens

Both fake dependencies but at different layers. Choosing the wrong layer either over-isolates or under-controls.

## Edge cases

- `cy.intercept()` cannot stub non-network calls; that is what `cy.stub()` is for.
- Stubbing `window.fetch` directly fights with intercept; pick one.
- GraphQL needs body-based matching in intercept.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_bRps9T4kOgifPIp7jV71nQ
