Quando usamos React Query em nossos projetos, temos uma série de funcionalidades poderosas ao nosso dispor: cache, refetch automático, invalidações, estados de carregamento e erro, etc. Mas tudo isso pode ser facilmente comprometido se mockarmos diretamente o useQuery
nos testes.
Neste artigo, vamos ver como usar o MSW (Mock Service Worker) para simular endpoints reais nos testes, preservando toda a inteligência do React Query — e evitando mocks frágeis e irreais.
🚫 O que NÃO fazer: mockar o useQuery
diretamente
jest.mock('@tanstack/react-query', () => ({
useQuery: () => ({ data: [{ id: 1, name: 'Test' }], isLoading: false }),
}));
Esse tipo de mock “quebra” toda a mágica do React Query:
- ❌ Não testa cache, nem invalidation
- ❌ Não simula estados reais como loading/error
- ❌ Cria um acoplamento forte e frágil entre seu componente e o teste
✅ O que fazer: usar MSW para simular o endpoint real
Com MSW, você intercepta requisições reais (fetch/axios) e devolve respostas mockadas — sem perder a lógica de cache, revalidação e fallback do React Query.
📦 Setup do MSW no projeto
1. Instale a lib
npm install msw --save-dev
2. Crie seus handlers
// src/mocks/handlers.ts
import { rest } from 'msw';
export const handlers = [
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json([{ id: 1, name: 'Rayza' }, { id: 2, name: 'Vitor' }])
);
}),
];
3. Configure o servidor para testes
// src/mocks/server.ts
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
4. Integre com Jest
// src/setupTests.ts
import '@testing-library/jest-dom';
import { server } from './mocks/server';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
E adicione no jest.config.ts
:
setupFilesAfterEnv: ['/src/setupTests.ts '],
🧪 Exemplo prático: testando listagem de usuários
Componente
// UserList.tsx
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
export function UserList() {
const { data, isLoading, error } = useQuery(['users'], async () => {
const res = await axios.get('/api/users');
return res.data;
});
if (isLoading) return <p>Loading...p>;
if (error) return <p>Error!p>;
return (
<ul>
{data.map((user: any) => (
<li key={user.id}>{user.name}li>
))}
ul>
);
}
Teste com MSW
// UserList.test.tsx
import { render, screen, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { UserList } from './UserList';
const queryClient = new QueryClient();
function renderWithClient(ui: React.ReactElement) {
return render(
<QueryClientProvider client={queryClient}>{ui}QueryClientProvider>
);
}
test('renders user list from mocked endpoint', async () => {
renderWithClient(<UserList />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('Rayza')).toBeInTheDocument();
expect(screen.getByText('Vitor')).toBeInTheDocument();
});
});
✅ Por que usar MSW?
Vantagens práticas:
- ✅ Você testa a integração real com a API (mesmo que fake)
- ✅ O React Query funciona de verdade: cache, refetch, status
- ✅ Você cobre casos de sucesso, erro, loading e até delay com
ctx.delay()
- ✅ Mocks mais fáceis de manter e reutilizar em testes E2E (Playwright/Cypress)
✨ Conclusão
Evitar mocks diretos de useQuery
é uma boa prática quando usamos React Query. Com o MSW, conseguimos simular uma API realista e manter todo o comportamento que faz do React Query uma ferramenta tão poderosa.
Mockar o endpoint, não o hook. Isso garante testes mais próximos da realidade, mais confiáveis e fáceis de evoluir.