DevPath · Aprenda a programar ESPTEN

Node.js, npm e testes

Testes assíncronos e dublês de teste (mocks)

Testar código assíncrono

Muito código real é assíncrono: pede dados a um servidor, lê um arquivo, espera um temporizador... Retorna promises. O desafio ao testá-lo é que o resultado não está disponível de imediato, então o teste deve esperar.

Há duas formas de fazer isso certo, e uma forma de fazer errado.

1. Marcar o teste como async e usar await

async function obterUsuario(id) {
  return { id, nome: "Ada" };  // na vida real faria um fetch
}

test("obterUsuario retorna o nome", async () => {
  const usuario = await obterUsuario(1);
  expect(usuario.nome).toBe("Ada");
});

2. Retornar a promise a partir do teste

Se você retornar a promise, o runner espera ela ser resolvida por você:

test("obterUsuario resolve", () => {
  return obterUsuario(1).then((u) => {
    expect(u.nome).toBe("Ada");
  });
});

O erro clássico: esquecer o await (ou o return). O teste termina antes de a promise ser resolvida e a asserção nunca é verificada: o teste "passa" mesmo que o código esteja quebrado. Se você testar async, sempre espere.

Dublês de teste: mocks e spies

Às vezes você não quer executar uma dependência real em um teste: enviar um e-mail, cobrar um cartão ou chamar uma API são lentos, custosos ou têm efeitos que não queremos nos testes. A solução são os dublês de teste: objetos falsos que substituem a dependência real.

A ideia central de um spy é guardar cada chamada para inspecioná-la depois:

function espiar(fn) {
  const espiao = (...args) => {
    espiao.chamadas.push(args);  // registra os argumentos
    return fn(...args);          // delega para a função real
  };
  espiao.chamadas = [];
  return espiao;
}

const somarEspiado = espiar((a, b) => a + b);
somarEspiado(2, 3);
somarEspiado(10, 1);
console.log(somarEspiado.chamadas);        // [[2, 3], [10, 1]]
console.log(somarEspiado.chamadas.length); // 2

Com isso, em um teste você pode afirmar coisas como "o botão de pagamento chamou cobrar exatamente uma vez com o valor correto", sem cobrar de verdade. Ferramentas como Jest ou Vitest trazem isso integrado (vi.fn(), jest.fn()), mas por dentro elas fazem exatamente o que você vê acima.

Exemplos

Um spy que conta chamadas e registra argumentos

function espiar(fn) {
  const espiao = (...args) => {
    espiao.chamadas.push(args);
    return fn(...args);
  };
  espiao.chamadas = [];
  return espiao;
}

const saudacao = espiar((nome) => "Olá, " + nome);
saudacao("Ada");
saudacao("Linus");
console.log("Retorna:", saudacao("Grace"));
console.log("Vezes chamado:", saudacao.chamadas.length);
console.log("Chamadas:", JSON.stringify(saudacao.chamadas));
Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
← Qualidade e empacotamentoVer o módulo →