msw para TypeScript: guia completo com exemplos práticos
O que é e para que serve?
Mock Service Worker (msw) é uma biblioteca para interceptar e simular requisições de rede no nível da Service Worker API. Diferente de soluções tradicionais (como axios-mock-adapter ou nock), o msw opera no nível do navegador ou Node.js, interceptando requisições HTTP reais e retornando respostas pré-definidas. Isso permite testar aplicações sem precisar rodar um servidor real ou modificar o código da aplicação.
O principal objetivo do msw é fornecer uma ferramenta unificada para simular APIs tanto em testes no navegador (usando um Service Worker real) quanto em testes no servidor (Node.js). A biblioteca é especialmente útil para desenvolvedores que usam TypeScript, pois oferece tipagem estrita para todas as requisições e respostas. O msw é ideal para testes unitários, testes de integração e também para desenvolvimento frontend isolado do backend.
A grande vantagem do msw é que as simulações funcionam no nível da rede, e não no nível do código. Isso significa que qualquer biblioteca para fazer requisições HTTP (fetch, axios, graphql-request, etc.) será interceptada automaticamente, sem configuração adicional. A biblioteca suporta REST API, GraphQL e também permite lidar com conexões WebSocket (através de extensões).
Instalação
Para instalar o msw em um projeto TypeScript, execute um dos seguintes comandos:
# npm
npm install msw --save-dev
# yarn
yarn add msw --dev
# pnpm
pnpm add msw --save-dev
Após a instalação, é necessário inicializar o Service Worker para uso no navegador:
npx msw init public/ --save
Para uso no servidor (Node.js), não é necessária inicialização adicional.
Início rápido — exemplo mínimo funcional
Vamos criar uma simulação simples para uma REST API. O exemplo inclui a definição do handler, a configuração do servidor e uma requisição de teste.
// handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('https://api.example.com/user', () => {
return HttpResponse.json({
id: 'c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3f',
firstName: 'João',
lastName: 'Silva',
});
}),
];
// server.ts (para Node.js)
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
// test.ts
import { server } from './server';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test('deve buscar o usuário', async () => {
const response = await fetch('https://api.example.com/user');
const data = await response.json();
expect(data.firstName).toBe('João');
});
Métodos e funções principais
1. http.get()
Assinatura: http.get(url: string | RegExp, resolver: (info: HttpRequestInfo) => HttpResponse)
Descrição: Cria um handler para requisições GET no URL especificado. Suporta strings exatas, expressões regulares e padrões com parâmetros.
import { http, HttpResponse } from 'msw';
export const handler = http.get('https://api.example.com/users/:id', ({ params }) => {
const { id } = params;
return HttpResponse.json({ id, nome: 'Usuário ' + id });
});
2. http.post()
Assinatura: http.post(url: string | RegExp, resolver: (info: HttpRequestInfo) => HttpResponse)
Descrição: Cria um handler para requisições POST. Permite ler o corpo da requisição através de request.json().
import { http, HttpResponse } from 'msw';
export const handler = http.post('https://api.example.com/users', async ({ request }) => {
const body = await request.json();
return HttpResponse.json({ mensagem: 'Usuário criado', dados: body }, { status: 201 });
});