Advanced Testing Patterns

Testing Async Code and API Calls

Test async operations, loading states, error handling, and network calls reliably.

Async Testing in Vitest

Vitest handles async tests naturally with async/await. Use async/await directly in test functions, use findBy queries for async renders, and use vi.useFakeTimers() for time-dependent code.

Testing Loading States in React

When testing components with async data loading:

  1. Assert loading state appears immediately after render
  2. Use findBy queries to wait for async content
  3. Assert loading indicator is gone after content loads
  4. Test error states by overriding server handlers

Mock Service Worker (MSW)

MSW intercepts network requests at the network level, making tests more realistic than mocking fetch directly. Set up handlers, a server, and configure setup/teardown in your test setup file.

Testing Debounced Functions

Use vi.useFakeTimers() to control time in tests. Type into the input, assert the function has NOT been called yet (debounced), advance time with vi.advanceTimersByTime(), then assert it was called exactly once.

Testing Streaming Responses (AI Features)

Create a ReadableStream with test chunks, mock fetch to return it, call the streaming function, and assert the assembled result matches the expected concatenation.

Key Takeaways

  • Use async/await directly in Vitest test functions — no special configuration needed
  • findBy queries wait for async renders; queryBy returns null (not throws) when element is absent
  • MSW intercepts at the network level — more realistic than mocking fetch
  • vi.useFakeTimers() controls setTimeout/setInterval/Date.now() for testing time-dependent code
  • Always reset fake timers after each test to prevent state leaking between tests

Example

typescript
// Testing async component with MSW
Try it yourself — TYPESCRIPT