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

Assert no Node.js: Guia Prático

Atualizado em: 10 de agosto de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Testes automatizados precisam comparar resultados, confirmar erros e interromper a execução quando uma condição não é atendida. O módulo nativo Assert no Node.js oferece funções para essas verificações sem instalar um framework externo.

Ele funciona muito bem com o Node Test Runner, scripts de validação e testes de bibliotecas. A versão strict evita coerções inesperadas e deve ser a escolha padrão em código novo.

Neste guia, você aprenderá a usar igualdade estrita, comparação profunda, rejeições assíncronas, validação de exceções, match, fail e mensagens de erro claras.

Importando Assert

const assert = require('node:assert/strict');

Em ES Modules:

import assert from 'node:assert/strict';

A documentação oficial de Assert descreve todas as asserções. Para organizar suítes, veja Node Test Runner. O guia da MDN sobre comparações em JavaScript ajuda a entender igualdade.

Por que usar a versão strict?

O módulo histórico possui comportamentos legados de igualdade não estrita. Ao importar node:assert/strict, métodos como equal() utilizam comparação estrita.

assert.equal(2 + 2, 4);

Esta asserção falha:

assert.equal('4', 4);

Evitar coerção reduz testes que passam por acidente.

assert.ok()

ok() confirma que um valor é truthy:

assert.ok(user);
assert.ok(items.length > 0);

Prefira uma comparação mais específica quando ela produzir uma mensagem melhor:

assert.equal(user.status, 'active');

equal() e notEqual()

assert.equal(result.statusCode, 200);
assert.notEqual(token, '');

Esses métodos comparam valores primitivos ou referências de objeto. Dois objetos com o mesmo conteúdo continuam sendo referências diferentes.

deepEqual()

assert.deepEqual(
  { id: 1, tags: ['node', 'test'] },
  { id: 1, tags: ['node', 'test'] }
);

A comparação profunda considera propriedades, arrays, Maps, Sets, objetos tipados e outras estruturas conforme as regras da versão do Node.js.

Objetos com propriedades extras

Esta comparação falha:

assert.deepEqual(
  { id: 1, name: 'Ana', role: 'admin' },
  { id: 1, name: 'Ana' }
);

Quando apenas alguns campos importam, selecione-os explicitamente:

assert.deepEqual(
  { id: user.id, name: user.name },
  { id: 1, name: 'Ana' }
);

Comparando arrays

assert.deepEqual(
  ['a', 'b', 'c'],
  ['a', 'b', 'c']
);

A ordem importa. Para conjuntos sem ordem, normalize primeiro ou use Set quando essa for a semântica correta.

Comparando Sets

assert.deepEqual(
  new Set(['a', 'b']),
  new Set(['b', 'a'])
);

Não converta automaticamente toda lista em Set, pois duplicatas podem ser relevantes.

Comparando Maps

assert.deepEqual(
  new Map([['status', 'ok']]),
  new Map([['status', 'ok']])
);

Chaves de objeto continuam seguindo identidade ou regras profundas conforme a implementação documentada.

throws()

throws() verifica código síncrono:

assert.throws(
  () => parsePort('invalid'),
  /Porta inválida/
);

Também é possível validar o tipo:

assert.throws(
  () => parsePort('invalid'),
  TypeError
);

Validando propriedades do erro

assert.throws(
  () => parseConfiguration({}),
  {
    name: 'ValidationError',
    code: 'CONFIG_INVALID'
  }
);

Não acople o teste a uma stack completa ou texto irrelevante. Prefira código, tipo e mensagem estável.

doesNotThrow()

assert.doesNotThrow(() => {
  validateConfiguration(validConfig);
});

Muitas vezes basta executar a função. Se ela lançar, o teste já falhará. Use doesNotThrow() quando a intenção ficar mais clara.

rejects()

Para Promises:

await assert.rejects(
  repository.findRequired('missing'),
  /Usuário não encontrado/
);

Também aceita uma função assíncrona:

await assert.rejects(
  async () => service.create(invalidInput),
  ValidationError
);

Sempre use await. Sem ele, o teste pode terminar antes da verificação.

doesNotReject()

await assert.doesNotReject(
  service.healthCheck()
);

Assim como no caso síncrono, aguardar a operação diretamente costuma ser suficiente.

match() e doesNotMatch()

assert.match(
  response.headers['content-type'],
  /^application\/json/
);
assert.doesNotMatch(
  publicMessage,
  /password|token/i
);

Evite expressões regulares excessivamente permissivas, que fazem o teste passar com valores incorretos.

ifError()

ifError() é útil ao testar callbacks legados:

legacyOperation((error, result) => {
  assert.ifError(error);
  assert.equal(result, 42);
});

Em código novo, prefira Promises e async/await.

fail()

if (!supportedPlatforms.includes(platform)) {
  assert.fail(`Plataforma inesperada: ${platform}`);
}

fail() marca um caminho que não deveria ser alcançado. Não use como substituto para asserções específicas.

Mensagens personalizadas

assert.equal(
  response.statusCode,
  201,
  'A criação deveria retornar HTTP 201'
);

Uma boa mensagem explica a regra esperada, sem repetir apenas os valores que o próprio Assert já mostra.

AssertionError

Quando uma asserção falha, o módulo lança AssertionError, contendo campos como actual, expected, operator e stack.

try {
  assert.equal(actual, expected);
} catch (error) {
  console.log(error.name);
  console.log(error.actual);
  console.log(error.expected);
}

Em testes normais, não capture o erro; deixe o runner exibi-lo.

Assert com Node Test Runner

const test = require('node:test');
const assert = require('node:assert/strict');

test('soma dois valores', () => {
  assert.equal(sum(2, 3), 5);
});

O runner organiza execução, hooks, mocks, paralelismo e relatórios, enquanto Assert realiza as comparações.

Testando APIs

test('retorna usuário', async () => {
  const response = await app.inject({
    method: 'GET',
    url: '/users/1'
  });

  assert.equal(response.statusCode, 200);
  assert.match(
    response.headers['content-type'],
    /^application\/json/
  );

  const body = response.json();
  assert.deepEqual(
    { id: body.id, name: body.name },
    { id: 1, name: 'Ana' }
  );
});

Valide contrato, status, headers e campos importantes. Não compare timestamps dinâmicos sem normalização.

Testando erros assíncronos

test('rejeita e-mail duplicado', async () => {
  await assert.rejects(
    () => service.createUser({ email: 'used@example.com' }),
    error => {
      assert.equal(error.code, 'EMAIL_EXISTS');
      return true;
    }
  );
});

O callback de validação deve retornar true quando o erro corresponde.

Valores de ponto flutuante

Não compare cálculos decimais diretamente quando há arredondamento:

const actual = 0.1 + 0.2;
assert.ok(Math.abs(actual - 0.3) < Number.EPSILON);

Para dinheiro, use inteiros em centavos ou uma biblioteca decimal adequada.

Datas

assert.equal(
  actualDate.toISOString(),
  '2026-08-10T12:00:00.000Z'
);

Normalize fuso e precisão. Comparar strings locais torna testes dependentes do ambiente.

Buffers

assert.deepEqual(
  Buffer.from('Node.js'),
  Buffer.from('Node.js')
);

Para criptografia e segredos, a comparação funcional pode exigir crypto.timingSafeEqual(), não Assert em produção.

Snapshots manuais

Assert não possui snapshots automáticos. É possível comparar um objeto normalizado com um JSON versionado, mas atualizações devem ser revisadas cuidadosamente.

Não use Assert para validar entrada em produção

Asserções representam invariantes do programa. Para dados de usuário, retorne erros de validação controlados:

if (typeof input.email !== 'string') {
  throw new ValidationError('E-mail obrigatório');
}

Uma AssertionError geralmente indica bug, não erro esperado do cliente.

Testes determinísticos

Controle relógio, aleatoriedade, rede e banco. Asserções boas não corrigem testes flakey. Use mocks apenas nas fronteiras necessárias e mantenha testes de integração para comportamento real.

Erros comuns

  • Usar assert legado: coerções escondem erros.
  • Esquecer await em rejects: o teste termina cedo.
  • Comparar objeto por equal: referências diferentes falham.
  • Comparar resposta inteira: campos dinâmicos tornam o teste frágil.
  • Validar mensagem completa: pequenas mudanças quebram a suíte.
  • Usar Assert para entrada externa: erros esperados viram falhas internas.
  • Comparar float exatamente: representação binária causa diferenças.

Boas práticas

  • Importe node:assert/strict.
  • Use a asserção mais específica.
  • Valide códigos e tipos de erro estáveis.
  • Aguarde todas as operações assíncronas.
  • Normalize datas, IDs e campos dinâmicos.
  • Selecione campos relevantes do contrato.
  • Mantenha mensagens personalizadas úteis.
  • Evite dependência de ordem quando não importa.
  • Separe testes unitários e de integração.
  • Trate AssertionError como indicação de bug.

Conclusão

O módulo Assert no Node.js oferece comparações expressivas para testes síncronos e assíncronos. Igualdade estrita, deepEqual, throws e rejects cobrem grande parte das necessidades sem dependências extras.

Testes confiáveis dependem de asserções específicas e dados determinísticos. Ao validar apenas o contrato relevante, aguardar Promises e evitar coerções, a suíte fica mais clara, rápida e resistente a mudanças que não alteram o comportamento.

Os 10 Melhores Cursos de Programação de 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