Testes em JavaScript: Unit, Integration, E2E — Guia Completo
Qualidade de código é a chave para o sucesso de qualquer projeto. No mundo JavaScript (especialmente Node.js), os testes se tornaram não apenas uma boa prática, mas uma necessidade. Analisamos três níveis principais: testes unitários (unit), de integração (integration) e ponta a ponta (E2E). Você aprenderá como eles diferem, quando aplicar cada tipo e verá exemplos práticos com ferramentas populares.
1. Testes Unitários: verificando módulos isolados
Testes unitários verificam o funcionamento de funções, classes ou módulos individuais isolados de dependências externas (banco de dados, API, sistema de arquivos). Este é o nível mais rápido e confiável.
Ferramentas e configuração
O framework mais popular é o Jest. Instalação:
npm install --save-dev jestAdicione o script no package.json:
"scripts": { "test": "jest"}Exemplo: testando uma função de cálculo de desconto
Crie o arquivo discount.js:
// discount.jsfunction applyDiscount(price, discountPercent) { if (price <= 0) throw new Error('Price must be positive'); if (discountPercent < 0 || discountPercent > 100) throw new Error('Invalid discount'); return price - (price * discountPercent) / 100;}module.exports = { applyDiscount };Agora escreva o teste unitário em discount.test.js:
const { applyDiscount } = require('./discount');
describe('applyDiscount', () => { test('calculates 10% discount correctly', () => { expect(applyDiscount(100, 10)).toBe(90); });
test('throws error for negative price', () => { expect(() => applyDiscount(-10, 10)).toThrow('Price must be positive'); });
test('throws error for invalid discount percent', () => { expect(() => applyDiscount(100, 150)).toThrow('Invalid discount'); });});Execução: npm test. O Jest encontrará automaticamente os arquivos *.test.js.
Dica: Use objetos mock para isolar serviços externos.
// Exemplo de mock de API externajest.mock('./api');const api = require('./api');api.getData.mockResolvedValue({ id: 1 });2. Testes de Integração: verificando a interação entre componentes
Testes de integração verificam como diferentes módulos trabalham juntos: banco de dados + lógica de negócios + rotas HTTP. Eles são mais lentos que os testes unitários, mas fornecem mais confiança na correção do sistema.
Ferramentas: Supertest + Jest
Supertest permite fazer requisições HTTP à sua aplicação Express sem precisar iniciar o servidor real.
npm install --save-dev supertestExemplo: testando uma REST API
Suponha que existe uma aplicação Express simples app.js:
const express = require('express');const app = express();app.use(express.json());
app.post('/users', (req, res) => { const { name, email } = req.body; if (!name || !email) { return res.status(400).json({ error: 'Missing fields' }); } // Salva no banco de dados (simplificado) res.status(201).json({ id: 1, name, email });});
module.exports = app;Teste de integração users.test.js:
const request = require('supertest');const app = require('./app');
describe('POST /users', () => { test('creates user with valid data', async () => { const response = await request(app) .post('/users') .send({ name: 'Alice', email: 'alice@test.com' }); expect(response.status).toBe(201); expect(response.body).toHaveProperty('id'); expect(response.body.name).toBe('Alice'); });
test('returns 400 for missing email', async () => { const response = await request(app) .post('/users') .send({ name: 'Bob' });