Back

Testes Unitários vs Testes de Integração em JavaScript: Quando Usar Cada Um

Testes Unitários vs Testes de Integração em JavaScript: Quando Usar Cada Um

Todo desenvolvedor JavaScript enfrenta a mesma questão ao construir aplicações confiáveis: devo escrever mais testes unitários ou testes de integração? Escolha errado e você passará horas depurando testes frágeis ou enviará bugs para produção. A resposta não é sobre escolher um em detrimento do outro—é sobre entender quando cada tipo entrega mais valor.

Este artigo esclarece as diferenças entre testes unitários e de integração em JavaScript, mostra exemplos práticos de cada um e fornece um framework de decisão para equilibrar ambos na sua estratégia de testes.

Principais Conclusões

  • Testes unitários verificam pedaços isolados de código para velocidade e precisão
  • Testes de integração validam interações entre componentes para confiança em cenários reais
  • Uma distribuição 70-20-10 (unitário-integração-E2E) funciona para a maioria dos projetos JavaScript
  • Escolha baseado no que você está testando: algoritmos precisam de testes unitários, fluxos de trabalho precisam de testes de integração

O Que São Testes Unitários?

Testes unitários verificam se pedaços individuais de código funcionam corretamente de forma isolada. Pense nisso como testar uma única peça de LEGO antes de adicioná-la à sua estrutura.

Em JavaScript, um teste unitário tipicamente foca em:

  • Uma única função ou método
  • Um componente sem seus filhos
  • Uma classe ou módulo específico

Exemplo de Teste Unitário

// calculator.js
export function calculateDiscount(price, percentage) {
  if (percentage < 0 || percentage > 100) {
    throw new Error('Invalid percentage');
  }
  return price * (1 - percentage / 100);
}

// calculator.test.js
import { calculateDiscount } from './calculator';

test('applies 20% discount correctly', () => {
  expect(calculateDiscount(100, 20)).toBe(80);
});

test('throws error for invalid percentage', () => {
  expect(() => calculateDiscount(100, 150)).toThrow('Invalid percentage');
});

Testes unitários se destacam em:

  • Velocidade: Milissegundos por teste, já que não há I/O ou dependências externas
  • Precisão: Identifica locais exatos de falhas
  • Estabilidade: Raramente quebra devido a mudanças não relacionadas

O Que São Testes de Integração?

Testes de integração verificam se múltiplas partes da sua aplicação funcionam corretamente juntas. Em vez de testar a peça de LEGO sozinha, você está testando como várias peças se conectam.

Testes de integração em JavaScript tipicamente cobrem:

  • Interações de componentes com APIs
  • Múltiplos módulos trabalhando juntos
  • Operações de banco de dados com lógica de negócio
  • Componentes de UI com gerenciamento de estado

Exemplo de Teste de Integração

// userProfile.test.js
import { render, screen, waitFor } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import UserProfile from './UserProfile';

const server = setupServer(
  rest.get('/api/user/:id', (req, res, ctx) => {
    return res(ctx.json({ 
      id: req.params.id, 
      name: 'Jane Doe',
      role: 'Developer' 
    }));
  })
);

beforeAll(() => server.listen());
afterAll(() => server.close());

test('displays user data after loading', async () => {
  render(<UserProfile userId="123" />);
  
  expect(screen.getByText(/loading/i)).toBeInTheDocument();
  
  await waitFor(() => {
    expect(screen.getByText('Jane Doe')).toBeInTheDocument();
    expect(screen.getByText('Developer')).toBeInTheDocument();
  });
});

Testes de integração fornecem:

  • Confiança: Valida fluxos de trabalho reais do usuário
  • Cobertura: Testa interação entre componentes
  • Realidade: Captura problemas que testes unitários perdem

Diferenças Principais Que Importam

Escopo e Isolamento

Testes unitários isolam código usando mocks e stubs. Você controla cada variável. Testes de integração usam implementações reais sempre que possível, mockando apenas limites externos como APIs ou bancos de dados.

Velocidade de Execução

Testes unitários executam em 1-50ms cada. Você pode executar milhares em segundos. Testes de integração levam 100-500ms ou mais. Eles envolvem setup, teardown e às vezes I/O real.

Custo de Manutenção

Testes unitários quebram apenas quando sua unidade específica muda. Testes de integração podem quebrar por mudanças em qualquer lugar do fluxo testado, exigindo mais tempo de investigação.

Detecção de Bugs

Testes unitários capturam erros de lógica e casos extremos em código isolado. Testes de integração capturam problemas de integração, suposições incorretas e violações de contrato entre componentes.

Quando Usar Cada Tipo

Escreva Testes Unitários Para:

  • Funções puras: Lógica de negócio, cálculos, transformações de dados
  • Algoritmos complexos: Ordenação, busca, regras de validação
  • Casos extremos: Tratamento de erros, condições de limite
  • Funções utilitárias: Formatadores, parsers, helpers

Escreva Testes de Integração Para:

  • Interações com API: Requisições HTTP, tratamento de respostas
  • Fluxos de trabalho do usuário: Processos multi-etapas, submissões de formulários
  • Integração de componentes: Comunicação entre componentes pai-filho
  • Gerenciamento de estado: Actions do Redux, fluxos da Context API
  • Operações de banco de dados: Operações CRUD com lógica de negócio

A Estratégia Prática de Testes

A maioria dos projetos JavaScript bem-sucedidos segue uma distribuição 70-20-10:

  • 70% Testes unitários: Feedback rápido, depuração fácil
  • 20% Testes de integração: Confiança nas interações entre componentes
  • 10% Testes end-to-end: Validação final de caminhos críticos

Esta não é uma regra rígida—ajuste baseado no tipo da sua aplicação. Aplicações com muitas APIs precisam de mais testes de integração. Bibliotecas com muitos algoritmos precisam de mais testes unitários.

Integração com Pipeline CI/CD

Estruture seu pipeline para feedback rápido:

  1. Pre-commit: Execute testes unitários (< 5 segundos)
  2. Pull request: Execute todos os testes unitários e de integração
  3. Pre-deploy: Execute a suíte completa de testes incluindo testes E2E

Ferramentas como Jest para testes unitários, Testing Library para testes de integração e MSW para mocking de APIs tornam este pipeline eficiente e sustentável.

Armadilhas Comuns a Evitar

  1. Excesso de mocking em testes de integração: Derrota o propósito de testar interações
  2. Testar detalhes de implementação: Foque no comportamento, não na estrutura interna
  3. Ignorar velocidade dos testes: Testes lentos desencorajam execução frequente
  4. Escrever testes após bugs: Testes proativos previnem problemas

Conclusão

Testes unitários e de integração em JavaScript não são estratégias concorrentes—são ferramentas complementares. Testes unitários oferecem velocidade e precisão para lógica isolada. Testes de integração fornecem confiança de que seus componentes funcionam corretamente juntos.

Comece com testes unitários para lógica de negócio e funções puras. Adicione testes de integração para caminhos críticos do usuário e interações entre componentes. Pule os debates religiosos sobre filosofias de testes e foque no que te dá confiança para entregar código.

A melhor estratégia de testes JavaScript é aquela que captura bugs antes dos usuários, mantendo sua velocidade de desenvolvimento alta. Balance ambos os tipos baseado nas necessidades da sua aplicação e ajuste conforme você aprende o que quebra mais frequentemente.

Perguntas Frequentes

Sempre mocke dependências externas em testes unitários. Isso inclui bancos de dados, APIs, sistemas de arquivos e outros serviços. Mocking garante que os testes executem rapidamente, permaneçam previsíveis e realmente testem seu código isoladamente ao invés do comportamento de sistemas externos.

Comece perguntando o que pode quebrar. Se a lógica em si é complexa, escreva testes unitários primeiro. Se a funcionalidade envolve múltiplos componentes se comunicando ou serviços externos, priorize testes de integração. A maioria das funcionalidades se beneficia de ambos os tipos.

Testes unitários devem completar em menos de 10 segundos para a suíte inteira. Testes de integração podem levar de 1 a 5 minutos. Se seus testes levam mais tempo, divida-os em jobs paralelos ou identifique testes lentos que precisam de otimização. Testes rápidos encorajam desenvolvedores a executá-los frequentemente.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay