Introdução: Por que testes sem mocks são como café sem cafeína?
\n\nImagine: você está escrevendo uma aplicação em TypeScript que envia e-mail, se comunica com um banco de dados e acessa uma API externa. Você executa os testes — e de repente tudo falha porque o servidor de e-mail está temporariamente indisponível. Familiar?
\n\nÉ aqui que entram em cena os objetos mock (simuladores) e as fixtures (dados de teste). Eles permitem isolar o código do mundo externo e tornar os testes rápidos, confiáveis e previsíveis. Neste artigo em português, vamos analisar com exemplos reais como usar corretamente o mock em TypeScript, quais são os tipos de fixtures para TypeScript e como não cometer erros.
\n\nO artigo foi escrito para o PythonLib — um portal educacional onde ensinamos a escrever código de qualidade. Vamos nessa!
\n\nO que são objetos mock e fixtures?
\n\nObjetos Mock: atores dublês no seu código
\n\nObjeto mock (ou simplesmente mock) é uma substituição de um objeto real que imita seu comportamento. Você diz: "Quando o método sendEmail() for chamado, retorne true". E o teste não acessa o e-mail real.
\n\nEm TypeScript, os mocks geralmente são criados com as bibliotecas Jest ou Vitest. Elas permitem verificar se o método foi chamado, com quais argumentos e quantas vezes.
\n\nFixtures: dados preparados para testes
\n\nFixtures são conjuntos de dados pré-preparados. Por exemplo, um objeto de usuário, uma lista de pedidos ou uma configuração de aplicação. Em vez de criá-los manualmente toda vez, você armazena as fixtures em arquivos separados.
\n\nA combinação de mock + fixture é o padrão de testes TypeScript em 2024.
\n\nPrática: escrevendo testes com mocks e fixtures
\n\nConfiguração do ambiente
\n\nPara os exemplos, usaremos o Jest (embora tudo funcione da mesma forma no Vitest). Certifique-se de ter as dependências instaladas:
\n\nnpm install --save-dev jest @types/jest ts-jest\n\nAdicione no jest.config.js:
module.exports = {\n preset: 'ts-jest',\n testEnvironment: 'node',\n};\n\nExemplo 1: Mock do serviço de envio de e-mail
\n\nSuponha que temos um serviço de notificações:
\n\n// notificationService.ts\nexport class EmailService {\n async sendEmail(to: string, subject: string, body: string): Promise<boolean> {\n // Envio real — não vamos mexer nisso\n return true;\n }\n}\n\nexport class NotificationManager {\n constructor(private emailService: EmailService) {}\n\n async notifyUser(email: string, message: string): Promise<string> {\n const result = await this.emailService.sendEmail(email, 'Notificação', message);\n return result ? 'Enviado' : 'Erro';\n }\n}\n\nAgora vamos escrever um teste com objeto mock:
\n\n// notificationService.test.ts\nimport { NotificationManager, EmailService } from './notificationService';\n\ndescribe('NotificationManager', () => {\n it('deve enviar a notificação e retornar "Enviado"', async () => {\n // Criando o mock\n const mockEmailService: jest.Mocked<EmailService> = {\n sendEmail: jest.fn().mockResolvedValue(true),\n };\n\n const manager = new NotificationManager(mockEmailService);\n const result = await manager.notifyUser('test@test.com', 'Olá!');\n\n expect(result).toBe('Enviado');\n expect(mockEmailService.sendEmail).toHaveBeenCalledWith(\n 'test@test.com',\n 'Notificação',\n 'Olá!'\n );\n });\n\n it('deve retornar "Erro" se o envio falhar', async () => {\n const mockEmailService: jest.Mocked<EmailService> = {\n sendEmail: jest.fn().mockResolvedValue(false),\n };\n\n const manager = new NotificationManager(mockEmailService);