October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

How to Mock Fetch and Test Error Handling in TypeScript

Use MSW to test the normal request path or a direct mock for a focused fetch contract. Keep HTTP error statuses distinct from rejected network requests.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For tests that should exercise your application’s normal fetch call, use Mock Service Worker (MSW) to intercept requests when it supports your test runtime. For a narrowly isolated unit test that only needs to check the fetch call’s arguments and result handling, a direct mock such as vi.fn() or jest.fn() can be simpler. Whichever approach you choose, keep an HTTP error response separate from a rejected fetch: a 404 response does not, by itself, take the same path as a network failure.

Choose between MSW and a direct fetch mock

Approach What the test replaces Best fit Trade-off
MSW request interception The outgoing request is intercepted; the application can call its ordinary fetch path. Request-level tests that should model request and response behavior. Requires reusable handlers and test-runner lifecycle setup.
Direct function mock The fetch function itself is replaced with a mock. A focused unit test of the arguments passed to fetch or how its result is handled. You must provide the response methods your code uses, and the test does not exercise the normal request path.

Vitest’s request-mocking guide recommends MSW for network request mocking and explains that its Node interception uses @mswjs/interceptors. MSW’s Node.js integration guide names both Jest and Vitest. Neither approach is universally best: choose based on what the test needs to prove.

As an Amazon Associate I earn from qualifying purchases.

Set up MSW for a TypeScript test

Keep request handlers separate from runner setup so they can be reused. The following pattern adapts the official MSW and Vitest guidance; it is not tied to a specific installed package version, so check the APIs and imports against the versions in your project.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Define handlers and configure the test lifecycle

Create a setup file such as test/server.ts:

import { afterAll, afterEach, beforeAll } from 'vitest'
import { setupServer } from 'msw/node'
import { http, HttpResponse } from 'msw'

export const server = setupServer(
  http.get('https://api.example.test/items', () =>
    HttpResponse.json([{ id: 'item-1' }]),
  ),
)

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

Register the file in Vitest’s setupFiles configuration. Starting the server before tests, resetting per-test handler overrides afterward, and closing the server at the end prevents overrides from leaking between tests. With onUnhandledRequest: 'error', an unhandled request fails loudly rather than silently becoming an accidental real network call. See the MSW quick start and Vitest’s request-mocking guide.

2. Call the production function in the test

With a handler registered for the endpoint, call the application function that normally makes the request and assert on its returned data or observable state. MSW’s quick start demonstrates making a fetch request against a registered endpoint and checking the parsed JSON result. This keeps the test focused on application behavior while intercepting the request at the network boundary.

Test success, HTTP errors, and network failures separately

These are different inputs with different application behavior. A response can arrive successfully at the transport level while carrying a non-OK status; a network failure means fetch rejects instead of returning a response.

Rank #2
TypeScript Programming Language - Software Engineer & Coder T-Shirt
  • TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
  • TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Successful response

Use a normal JSON response for the success path:

http.get('https://api.example.test/items', () =>
  HttpResponse.json([{ id: 'item-1' }]),
)

Assert that the production function returns or exposes the parsed items, depending on its contract.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

HTTP response with an error status

Return an actual HTTP response carrying the status you want to exercise. If the production function should treat non-OK responses as errors, it needs to check response.ok or the relevant status and throw an application-level error itself. Fetch does not turn an HTTP 404 or 500 into a rejected promise merely because of that status.

http.get('https://api.example.test/items', () =>
  HttpResponse.json({ message: 'Not found' }, { status: 404 }),
)

Then assert the contract your function implements—for example, that it throws a domain-specific error after inspecting the response. Do not use HttpResponse.error() for this case: it represents a network failure, not a response whose status the application can inspect.

Rejected fetch or network failure

Use MSW’s HttpResponse.error() to simulate a network error:

server.use(
  http.get('https://api.example.test/items', () =>
    HttpResponse.error(),
)
)

The documented Fetch API behavior is a generic TypeError: Failed to fetch. MSW does not let this API customize the message, so assert that the function rejects or enters its error state rather than checking for DNS-, timeout-, or other environment-specific wording. The distinction and limitation are described in MSW’s network errors guide.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Handle caught values safely in TypeScript

In TypeScript, a caught value should be treated as unknown: thrown values are not guaranteed to be Error instances. Narrow the value before reading message so the error path remains safe:

try {
  return await loadItems()
} catch (error: unknown) {
  const message = error instanceof Error
    ? error.message
    : 'Could not load items'

  return { error: message }
}

Test both an Error rejection and, if your function is intended to handle arbitrary thrown values, a non-Error value. Keep this separate from the HTTP-status branch: the latter only reaches a catch block if your own code turns that response into a thrown error.

Use a direct mock when the fetch contract is the point

A direct mock is useful when the test needs to verify a narrow contract, such as the URL, method, or headers passed to fetch, without setting up request interception. Configure it to return a promise resolving to an object with the response methods the production code calls, such as json() or text(). Configure a rejected promise for the network-failure case.

Be careful with module mocks that replace the response class as well as fetch. Jest’s 30.0 documentation shows that jest.mock('node-fetch') can also mock Response, leaving methods such as response.text() unavailable; its example retrieves the actual response with jest.requireActual. See Jest’s “Bypassing module mocks” guide. Do not combine a node-fetch response with an unrelated global fetch implementation: use the response type that matches the runtime and module your code actually uses.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep runtime-specific behavior in scope

The test environment determines which web APIs and fetch implementation are available. Vitest notes that its Node environment affects available web APIs and presents MSW as a way to mimic network behavior. Confirm your project’s configured environment and globals before relying on a particular implementation.

Abort behavior is another distinct case. The node-fetch documentation describes abort rejections as AbortError and other operational failures as FetchError; that taxonomy applies to node-fetch and should not be assumed for browser fetch or every runtime. See node-fetch error handling.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.