ts-mockito para TypeScript: guia completo com exemplos
1. O que é e para que serve
ts-mockito é uma biblioteca poderosa para criar mocks, stubs e spies em TypeScript. Inspirada na popular biblioteca Mockito do Java, ela oferece uma API familiar para desenvolvedores que estão migrando do Java ou Python. O principal objetivo do ts-mockito é simplificar a escrita de testes unitários, isolando o código testado de dependências externas como bancos de dados, clientes HTTP, sistemas de arquivos e outros serviços.
Por que isso é importante? Em aplicações TypeScript modernas, classes e funções frequentemente dependem de outros componentes. Sem mocks, testar essas conexões se transforma em um teste de integração, que exige configuração de ambiente. O ts-mockito permite criar objetos "falsos" com comportamentos predefinidos e verificar quais métodos foram chamados e com quais argumentos. Isso torna os testes rápidos, determinísticos e fáceis de manter.
A biblioteca suporta todos os recursos principais do Mockito: criação de mocks com mock(), configuração de comportamento com when() e thenReturn(), verificação de chamadas com verify() e trabalho com spies usando spy(). O ts-mockito é totalmente tipado e se integra perfeitamente com frameworks de teste populares como Jest, Mocha e Jasmine.
2. Instalação
A instalação do ts-mockito é feita via npm (Node Package Manager). Execute o seguinte comando na raiz do seu projeto:
npm install ts-mockito --save-dev
Se você usa yarn:
yarn add ts-mockito --dev
A biblioteca não possui dependências obrigatórias, além do próprio TypeScript (versão 4.0+). Após a instalação, você pode importar as funções necessárias nos seus arquivos de teste:
import { mock, when, verify, instance, anything, anyOfClass, deepEqual, spy } from 'ts-mockito';
Importante: o ts-mockito usa objetos proxy para interceptar chamadas. Isso significa que você sempre trabalha com objetos "encapsulados", e não com instâncias reais das classes.
3. Início rápido — exemplo mínimo funcional
Vamos ver um exemplo simples: temos uma classe UserService que depende de UserRepository. Queremos testar o método getUser sem acessar um banco de dados real.
// user-repository.ts
export class UserRepository {
async findById(id: number): Promise<{ id: number; name: string } | null> {
// Consulta real ao banco de dados
return null;
}
}
// user-service.ts
export class UserService {
constructor(private repository: UserRepository) {}
async getUser(id: number): Promise<string> {
const user = await this.repository.findById(id);
if (!user) {
throw new Error('Usuário não encontrado');
}
return `Usuário: ${user.name}`;
}
}
// user-service.spec.ts
import { mock, when, instance, verify, anything } from 'ts-mockito';
import { UserService } from './user-service';
import { UserRepository } from './user-repository';
describe('UserService', () => {
it('deve retornar o nome do usuário quando ele existir', async () => {
// 1. Criamos um mock do repositório
const mockRepository: UserRepository = mock(UserRepository);
// 2. Configuramos o comportamento: ao chamar findById(1), retornamos um objeto
when(mockRepository.findById(1)).thenResolve({ id: 1, name: 'Alice' });
// 3. Obtemos a instância real do mock
const repositoryInstance = instance(mockRepository);
// 4. Instanciamos o serviço com o mock
const service = new UserService(repositoryInstance);
// 5. Executamos o método a ser testado
const result = await service.getUser(1);
// 6. Verificamos o resultado
expect(result).toBe('Usuário: Alice');
// 7. Verificamos se o método foi chamado corretamente
verify(mockRepository.findById(1)).once();
});
});
Neste exemplo, o mock substitui o repositório real, permitindo testar o UserService de forma isolada e rápida.