<h2>Fundamentos de Testes em React com Testing Library</h2>
<p>A Testing Library é uma biblioteca que enfatiza testes centrados no usuário, não na implementação. Ao contrário do Enzyme, que permite acessar estados internos, a Testing Library força você a testar como um usuário realmente interage com sua aplicação. Isso significa buscar elementos pelo texto visível, labels, placeholders e roles ARIA — nunca por seletores de classe ou ID diretos.</p>
<p>O primeiro passo é entender a hierarquia de queries. Existem três categorias: <code>getBy</code> (lança erro se não encontrar), <code>queryBy</code> (retorna null) e <code>findBy</code> (assíncrono, ideal para elementos que aparecem após renderização). Para começar, instale as dependências:</p>
<pre><code class="language-bash">npm install --save-dev @testing-library/react @testing-library/jest-dom vitest</code></pre>
<p>Aqui está um exemplo funcional de um teste básico:</p>
<pre><code class="language-javascript">import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from './LoginForm';
describe('LoginForm', () => {
it('deve exibir mensagem de sucesso ao enviar', async () => {
render(<LoginForm />);
const emailInput = screen.getByLabelText(/email/i);
const submitButton = screen.getByRole('button', { name: /entrar/i });
await userEvent.type(emailInput, 'user@example.com');
await userEvent.click(submitButton);
const successMessage = await screen.findByText(/bem-vindo/i);
expect(successMessage).toBeInTheDocument();
});
});</code></pre>
<h2>Mock de APIs com MSW (Mock Service Worker)</h2>
<p>MSW intercepta requisições HTTP no nível da rede, sem alterar seu código. Funciona tanto em testes quanto no desenvolvimento real. Configure handlers que definem como a rede deve responder:</p>
<pre><code class="language-bash">npm install --save-dev msw</code></pre>
<p>Crie um arquivo de configuração para seus handlers:</p>
<pre><code class="language-javascript">// src/mocks/handlers.js
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('https://api.example.com/users/:id', ({ params }) => {
return HttpResponse.json({
id: params.id,
name: 'João Silva',
email: 'joao@example.com'
});
}),
http.post('https://api.example.com/login', async ({ request }) => {
const body = await request.json();
if (body.password === 'correct') {
return HttpResponse.json({ token: 'abc123' }, { status: 200 });
}
return HttpResponse.json({ error: 'Inválido' }, { status: 401 });
})
];</code></pre>
<p>Configure o servidor MSW no seu setup de testes:</p>
<pre><code class="language-javascript">// src/mocks/server.js
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);</code></pre>
<p>No arquivo de configuração do seu test runner (vitest.config.js):</p>
<pre><code class="language-javascript">import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/mocks/setupTests.js'
}
});</code></pre>
<p>E em setupTests.js:</p>
<pre><code class="language-javascript">import { beforeAll, afterEach, afterAll } from 'vitest';
import { server } from './mocks/server';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());</code></pre>
<h2>Estratégias Avançadas de Mock</h2>
<p>Existem situações onde você precisa sobrescrever handlers padrão ou mockar de forma granular. Use <code>server.use()</code> para injetar handlers específicos em testes individuais:</p>
<pre><code class="language-javascript">import { http, HttpResponse } from 'msw';
import { server } from './mocks/server';
describe('UserProfile', () => {
it('deve exibir erro quando API falha', async () => {
// Sobrescreve o handler padrão
server.use(
http.get('https://api.example.com/users/:id', () => {
return HttpResponse.json(
{ error: 'Não encontrado' },
{ status: 404 }
);
})
);
render(<UserProfile userId="1" />);
const errorMessage = await screen.findByText(/não encontrado/i);
expect(errorMessage).toBeInTheDocument();
});
});</code></pre>
<p>Para dados complexos ou múltiplas requisições, considere usar factory functions:</p>
<pre><code class="language-javascript">// src/mocks/factories.js
export function createUser(overrides = {}) {
return {
id: '1',
name: 'Padrão',
email: 'padrao@example.com',
role: 'user',
...overrides
};
}
export function createApiError(status = 500, message = 'Erro') {
return { status, message };
}</code></pre>
<p>Outro padrão importante é mockar módulos locais. Use <code>vi.mock()</code> para casos onde você precisa controlar comportamentos de utilidades ou serviços:</p>
<pre><code class="language-javascript">import { vi } from 'vitest';
import { calculateDiscount } from './utils';
vi.mock('./utils', () => ({
calculateDiscount: vi.fn(() => 0.20)
}));
it('aplica desconto correto', () => {
expect(calculateDiscount(100)).toBe(0.20);
});</code></pre>
<h2>Boas Práticas e Anti-padrões</h2>
<p>Teste comportamentos, não implementações. Evite testar estado interno ou métodos privados — isso torna testes frágeis e acoplados. Quando um teste quebra porque você refatorou componentes internos (mantendo a funcionalidade), isso sinaliza um teste mal escrito.</p>
<p>Sempre use <code>screen</code> em vez de <code>render().container</code>. A Testing Library remove acesso direto ao DOM exatamente para encorajar consultas acessíveis. Nunca faça:</p>
<pre><code class="language-javascript"></code></pre>
<p>Aguarde elementos assincronamente com <code>findBy</code> ao invés de <code>getBy</code> para requisições:</p>
<pre><code class="language-javascript"></code></pre>
<h2>Conclusão</h2>
<p>Testes em React com Testing Library, MSW e estratégias de mock consolidam três pilares: <strong>1)</strong> Testing Library força testes centrados no usuário, eliminando testes frágeis acoplados à implementação; <strong>2)</strong> MSW fornece interceptação de rede real sem poluir seu código, sendo reutilizável entre testes e desenvolvimento; <strong>3)</strong> Mocking granular com <code>server.use()</code> e <code>vi.mock()</code> oferece controle fino sem sacrificar clareza. Domine esses fundamentos e seus testes se tornarão uma segurança real, não apenas cobertura numérica.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://testing-library.com/docs/react-testing-library/intro/" target="_blank" rel="noopener noreferrer">Testing Library Documentation</a></li>
<li><a href="https://mswjs.io/" target="_blank" rel="noopener noreferrer">Mock Service Worker - MSW Official Docs</a></li>
<li><a href="https://vitest.dev/" target="_blank" rel="noopener noreferrer">Vitest - Unit Testing Framework</a></li>
<li><a href="https://kentcdodds.com/blog/common-mistakes-with-react-testing-library" target="_blank" rel="noopener noreferrer">Common mistakes with React Testing Library - Kent C. Dodds</a></li>
<li><a href="https://martinfowler.com/articles/practical-test-pyramid.html" target="_blank" rel="noopener noreferrer">The Practical Test Pyramid - Martin Fowler</a></li>
</ul>