Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Mocking no Node.js: spies, stubs e fakes

Atualizado em: 12 de outubro de 2026

Terminal Linux usado em desenvolvimento e administração de aplicações Node.js

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.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita