Testes em TypeScript: unit, integration, e2e do A ao Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que testar em TypeScript é um must have

TypeScript — uma ferramenta poderosa que adiciona tipagem estática ao JavaScript. No entanto, mesmo o sistema de tipos mais rigoroso não garante que seu código funcionará corretamente em tempo de execução. Bugs, erros lógicos, tratamento incorreto de casos extremos — tudo isso fica fora do escopo da compilação. É aqui que os testes entram em cena.

Neste artigo, vamos abordar três níveis principais de teste em TypeScript: unit (unitário), integration (integração) e e2e (ponta a ponta). Você aprenderá como eles diferem, quando aplicar cada um e verá exemplos reais de código. Após a leitura, você será capaz de configurar um pipeline de testes completo para seu projeto TypeScript.



1. Testes unitários: verificando unidades atômicas de código

Testes unitários são o nível de verificação mais rápido e barato. Eles isolam uma única função, método ou classe e a testam separadamente das dependências externas (bancos de dados, APIs, sistema de arquivos).



1.1 Escolha da ferramenta e configuração

O framework mais popular para TypeScript é o Jest. Ele possui suporte nativo a TypeScript através de ts-jest ou @swc/jest.

// Instalaçãonpm install --save-dev jest @types/jest ts-jest

// Inicialização da configuraçãonpx ts-jest config:init

Após isso, o arquivo jest.config.js com as configurações aparecerá na raiz.



1.2 Exemplo de teste unitário para uma função

Suponha que temos uma função simples para calcular desconto:

// discount.tsexport function applyDiscount(price: number, discountPercent: number): number {  if (discountPercent < 0 || discountPercent > 100) {    throw new Error('Porcentagem de desconto inválida');  }  return price - (price * discountPercent) / 100;}

Vamos escrever um teste unitário para ela:

// discount.test.tsimport { applyDiscount } from './discount';

describe('applyDiscount', () => { it('deve calcular corretamente o desconto de 10%', () => { expect(applyDiscount(1000, 10)).toBe(900); });

it('deve retornar o preço original com desconto de 0%', () => { expect(applyDiscount(500, 0)).toBe(500); });

it('deve lançar erro para desconto maior que 100%', () => { expect(() => applyDiscount(100, 150)).toThrow('Porcentagem de desconto inválida'); });});

Execute: npx jest. Todos os três testes devem passar em verde.



1.3 Mocks e stubs

Se a função acessa um serviço externo (por exemplo, banco de dados), substituímos por um mock:

// userService.test.tsimport { getUser } from './userService';import { db } from './database';

jest.mock('./database'); // Mock automático

test('getUser retorna usuário por ID', async () => { (db.findUser as jest.Mock).mockResolvedValue({ id: 1, name: 'João' }); const user = await getUser(1); expect(user.name).toBe('João');});


2. Testes de integração: verificando a interação entre módulos

Testes de integração verificam como diferentes partes do sistema funcionam juntas: controladores, serviços, repositórios, bancos de dados. Eles são mais lentos que os testes unitários, mas fornecem mais confiança na correção das conexões.



2.1 Testando um endpoint de API com Express

Para testar requisições HTTP, usamos a biblioteca Supertest junto com Jest.

// Instalaçãonpm install --save-dev supertest @types/supertest

Suponha que temos uma aplicação Express:

// app.tsimport express from 'express';import { createUser } from './controllers/userController';

export const app = express();app.use(express.json());app.post('/api/users', createUser);

Teste de integração:

// app.test.tsimport request from 'supertest';import { app } from './                

Blogs

Book Recommendations