Mocking no Node.js é a técnica de substituir uma dependência real por uma implementação controlada durante testes. Mocks ajudam a simular banco, relógio, cliente HTTP, fila, logger e outras fronteiras sem executar o serviço externo.
O objetivo não é falsificar tudo. Bons testes usam mocks para isolar comportamento específico e deixam integrações importantes serem verificadas em testes próprios.
Neste guia, você aprenderá spies, stubs, funções falsas, injeção de dependência, relógio controlado, módulos, limpeza e erros comuns.
Fake, stub e spy
- fake: implementação simplificada funcional;
- stub: retorna resposta preparada;
- spy: registra chamadas;
- mock: combina comportamento e expectativas.
Mock de método com node:test
import test from 'node:test';
import assert from 'node:assert/strict';
test('registra usuário criado', (t) => {
const logger = { info() {} };
const spy = t.mock.method(logger, 'info');
logger.info({ userId: '123' }, 'Usuário criado');
assert.equal(spy.mock.callCount(), 1);
});Stub de retorno
test('busca pelo repositório', async (t) => {
const repository = { buscar() {} };
t.mock.method(repository, 'buscar', async () => ({ id: '123' }));
const service = criarService({ repository });
const result = await service.buscar('123');
assert.equal(result.id, '123');
});Injeção de dependência
A forma mais simples de testar é tornar dependências explícitas:
export function criarService({ repository, clock, logger }) {
return {
async criar(input) {
const entity = { ...input, createdAt: clock.now() };
await repository.salvar(entity);
logger.info({ id: entity.id }, 'Criado');
return entity;
}
};
}O teste fornece objetos pequenos sem alterar imports globais.
Relógio falso
const clock = {
now() {
return new Date('2026-01-10T12:00:00Z');
}
};Datas fixas eliminam flutuação e permitem verificar expiração, TTL e janelas de tempo.
Gerador de IDs
const idGenerator = {
next() {
return 'fixed-id';
}
};Injetar geradores evita depender de valores aleatórios.
Cliente HTTP falso
const httpClient = {
async get(url) {
return { status: 200, body: { active: true } };
}
};Teste timeout, 500, resposta inválida e cancelamento em casos separados.
Não faça mock de tudo
Se o teste substitui todas as camadas, ele apenas confirma que o mock retorna o valor configurado. Mantenha lógica real suficiente para detectar regressões.
Fakes em memória
function criarRepositoryFake() {
const data = new Map();
return {
async salvar(entity) {
data.set(entity.id, structuredClone(entity));
},
async buscar(id) {
return data.get(id) ?? null;
}
};
}Um fake pode ser mais útil que dezenas de expectativas de chamadas.
Verificando argumentos
const call = spy.mock.calls[0];
assert.equal(call.arguments[0].userId, '123');Verifique somente argumentos relevantes ao contrato. Assertar cada detalhe torna o teste frágil.
Erros simulados
t.mock.method(repository, 'salvar', async () => {
const error = new Error('Banco indisponível');
error.code = 'DB_DOWN';
throw error;
});Caminhos negativos precisam ser testados: retry, tradução de erro, rollback e log seguro.
Mocks de módulos
Substituir imports diretamente pode depender do formato ESM ou CommonJS e do suporte da ferramenta. Prefira módulos com fábricas e dependências injetáveis.
Consulte ESM no Node.js e CommonJS no Node.js.
Limpeza automática
Mocks criados pelo contexto de teste devem ser restaurados ao final. Evite compartilhar objetos mockados entre testes concorrentes.
Ordem de chamadas
Assertar ordem é apropriado quando ela faz parte do contrato, como iniciar transação antes de salvar. Não verifique ordem apenas porque a implementação atual funciona assim.
Mock de logger
O teste pode verificar nível e campos estruturados sem depender do texto completo. Nunca inclua segredos em fixtures de log.
Teste de contrato do fake
Se vários testes usam um fake de repositório, execute a mesma suíte contra o fake e a implementação real. Isso reduz divergência semântica.
Quando usar integração real
- queries e transações;
- serialização HTTP;
- filas e acknowledgements;
- cache distribuído;
- permissões de arquivos;
- migrações.
Mocks não comprovam que essas integrações estão configuradas corretamente.
Erros comuns
- mockar a unidade sob teste;
- assertar detalhes internos;
- compartilhar mock entre casos;
- não restaurar método;
- simular resposta impossível;
- usar sleep em vez de relógio falso;
- não testar erros;
- substituir integrações em toda a suíte.
Checklist
- dependências explícitas;
- mocks pequenos;
- fakes com contrato;
- argumentos essenciais verificados;
- caminhos negativos;
- limpeza por teste;
- sem estado compartilhado;
- integração real em suíte própria.
Conclusão
Mocking no Node.js funciona melhor como ferramenta de design. Quando uma classe ou função é difícil de testar sem manipular o runtime inteiro, provavelmente suas dependências estão escondidas.
Prefira injeção explícita, fakes pequenos e expectativas focadas no comportamento. Combine testes unitários rápidos com testes de integração para obter confiança real.
Consulte a documentação oficial de mocking do node:test e a referência do test runner.



