Setup
import * as React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
export function createTestWrapper() {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
})
return function TestWrapper(props: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
{props.children}
</QueryClientProvider>
)
}
}
Core Patterns
Create a client per test
import { QueryClient } from '@tanstack/react-query'
export function createTestQueryClient() {
return new QueryClient({
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
})
}
Await async state
import { QueryClient } from '@tanstack/react-query'
export async function loadTodosForTest() {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
})
return queryClient.fetchQuery({
queryKey: ['todos'],
queryFn: async () => [{ id: 1 }],
})
}
Clear after direct client tests
import { QueryClient } from '@tanstack/react-query'
export function dispose(queryClient: QueryClient) {
queryClient.clear()
}
Common Mistakes
CRITICAL Shared test client
Wrong:
import { QueryClient } from '@tanstack/react-query'
export const queryClient = new QueryClient()
Correct:
import { QueryClient } from '@tanstack/react-query'
export function createQueryClient() {
return new QueryClient({ defaultOptions: { queries: { retry: false } } })
}
A shared client leaks cache and mutation state across tests.
Source: TanStack/query:docs/framework/react/guides/testing.md
HIGH Retry backoff in tests
Wrong:
import { QueryClient } from '@tanstack/react-query'
export const queryClient = new QueryClient()
Correct:
import { QueryClient } from '@tanstack/react-query'
export const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
})
Default retries delay failure and make tests look hung.
Source: TanStack/query:docs/framework/react/guides/testing.md
HIGH Asserting before async success
Wrong:
import { QueryClient } from '@tanstack/react-query'
const queryClient = new QueryClient()
const promise = queryClient.fetchQuery({
queryKey: ['todos'],
queryFn: async () => [{ id: 1 }],
})
console.log(queryClient.getQueryData(['todos']))
await promise
Correct:
import { QueryClient } from '@tanstack/react-query'
const queryClient = new QueryClient()
await queryClient.fetchQuery({
queryKey: ['todos'],
queryFn: async () => [{ id: 1 }],
})
console.log(queryClient.getQueryData(['todos']))
Query state is asynchronous; assert after the query promise resolves or the UI wait completes.
Source: TanStack/query:docs/framework/react/guides/testing.md