React: From Components to Production · Testing and Accessibility

Testing Async UI with MSW

Mock the network instead of modules for realistic data-fetching tests.

Mock Service Worker (MSW) intercepts network requests in tests (Node) and the browser, so components use their real fetching code (TanStack Query, fetch) against mocked HTTP responses. Define handlers per endpoint, override them per test for error cases, and wrap components in fresh providers (a new QueryClient with retries disabled) for isolation.

import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const server = setupServer(
  http.get("/api/orders", () => HttpResponse.json({ items: [{ id: "1", number: "A-100" }], total: 1 })),
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

function renderWithClient(ui: React.ReactElement) {
  const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return render(<QueryClientProvider client={client}>{ui}</QueryClientProvider>);
}

it("shows orders", async () => {
  renderWithClient(<Orders />);
  expect(await screen.findByText("A-100")).toBeInTheDocument();
});

it("shows an error state", async () => {
  server.use(http.get("/api/orders", () => new HttpResponse(null, { status: 500 })));
  renderWithClient(<Orders />);
  expect(await screen.findByRole("alert")).toBeInTheDocument();
});

Common pitfalls

  • Sharing one QueryClient across tests (cached data leaks between tests).
  • Leaving retries enabled, making error tests slow.
  • Mocking fetch module internals instead of HTTP.

Key points

  • MSW mocks HTTP, not modules
  • Fresh QueryClient per test
  • Test success, loading and error states

Further reading: MSW documentation

Practice questions

Why mock at the network level with MSW instead of mocking your API module?

Answer

Components exercise their real data-fetching code paths, tests are less coupled to implementation, and the same handlers can be reused in the browser for development.

Why disable retries in tests using TanStack Query?

Answer

Default retries with backoff delay error states by several seconds, making tests slow or time out.

Open in the app to mark lessons complete, take notes and track your progress.