DEV Community

Jhony Walker
Jhony Walker

Posted on

Typescript e Jest - Escrevendo testes unitários em um projeto Node.js

Triade dos testes

Todos nós sabemos a importância de testes em nosso código, precisamos deles para evitar os temidos bugs e torna-lá cada vez mais escalavél. O objetivo deste post é mostrar como executar testes unitários com Jest e TypeScript de forma objetiva, clara e direta ao ponto.

Primeiros passos

Para realizarmos nossos primeiros testes com Jest precisamos de criar um projeto Node.js (ou React.js mas nesse post vamos utilizar um projeto em Node.js), para isso vamos iniciar um projeto. Gosto de criar meus projetos na area de trabalho portanto faço o seguinte ao abrir o terminal:

cd desktop
Enter fullscreen mode Exit fullscreen mode

Ao acessar o terminal realizo a criação da pasta do projeto:

mkdir tests-node-jest
Enter fullscreen mode Exit fullscreen mode

Agora vamos acessar a pasta:

cd tests-node-jest
Enter fullscreen mode Exit fullscreen mode

e por fim vamos iniciar o projeto em Node.js:

npm init -y ou yarn init -y
Enter fullscreen mode Exit fullscreen mode

Como vamos utilizar o Typescript temos que instalar o mesmo em nosso projeto:

npm install typescript -D ou yarn add typescript -D
Enter fullscreen mode Exit fullscreen mode

Precisaremos também do Jest para começar a escrever nossos testes:

npm install jest -D ou yarn add jest -D
Enter fullscreen mode Exit fullscreen mode

Por fim já que estamos utilizando o Typescript precisaremos instalar o pacote ts-jest e outro pacote com as tipagens do Jest:

npm install ts-jest -D ou yarn add ts-jest -D
npm install @types/jest -D ou yarn add @types/jest -D
Enter fullscreen mode Exit fullscreen mode

Configuração

Antes de iniciar os testes você precisar configurar o preset. No Jest o preset é um conjunto de configurações que servem de base.Embora essas configurações sejam muito simples, o ts-jest disponibiliza um comando para criar o arquivo jest.config.js com o preset correto.

npx ts-jest config:init
Enter fullscreen mode Exit fullscreen mode

Executando Testes com Jest e TypeScript

Por padrão o Jest executa todos os arquivos que ficam na pasta tests ou que tenham os trechos test ou spec no nome do arquivo.

Digamos que você tenha o arquivo /src/index.ts:

export function double(x: number): number {
  return x * 2;
}

export function concat(...args: string[]): string {
  return args.reduce((result, param) => result + param, '');
}
Enter fullscreen mode Exit fullscreen mode

Para testar essas funções basta você criar o arquivo __tests__/index.test.ts:

import { double, concat } from '../src/index';

describe('testing index file', () => {
  test('double function', () => {
    expect(double(5)).toBe(10);
  });

  test('concat function', () => {
    expect(concat('John', ' ', 'Wick')).toBe('John Wick');
  });
});
Enter fullscreen mode Exit fullscreen mode

Este exemplo contém um grupo de testes definido pela função describe e dentro do grupo tem dois testes definidos com a função test. Lembrando que também é possível criar sub-grupos com a função describe.

Dentro da função test você precisa declarar uma expectativa seguida de um matcher. Neste exemplo, expect é a expectativa e toBe é o matcher. Ou seja, você espera que o retorno de uma função (ou uma varíavel) seja igual a um determinado valor.

Para realizar os testes, execute este comando:

npx jest
Enter fullscreen mode Exit fullscreen mode

Agora se algum teste falhar o Jest vai mostrar uma mensagem de erro. Como estamos utilizando Jest e TypeScript, vale destacar que inconsistências de tipos também serão apresentadas.

Aperfeiçoando seus Testes

O exemplo que mostrei é algo muito simples, mas conforme seu software cresce seus testes também crescerão e provavelmente você precisará de funcionalidades mais avançadas. O matcher mais comum é o toBe e que funciona muito bem para comparar valores primitivos, porém com o tempo você precisará de matchers mais avançados. Eu fiz uma lista com os matchers mais populares:

  • toEqual - Útil para verificar objetos e suas propriedades
  • toBeFalsy - Útil para verificar valores que podem ser convertidos para false por meio da coerção do JavaScript.
  • toBeTruthy - Útil para verificar valores que podem ser convertidos para true por meio da coerção do JavaScript.
  • toContain - Útil para verificar arrays com valores primitivos.
  • toContainEqual - Útil para verificar arrays com objetos.
  • toMatch - Útil para verificar strings e expressões regulares (Regex).
  • toThrow - Útil para verificar se uma função lançou uma exceção.

Algo muito interessante sobre os matchers, é que se você usar o prefixo .not a condição será invertida. Por exemplo:

expect(1).not.toBe(2);
Enter fullscreen mode Exit fullscreen mode

Se você deseja ver todos os matchers na documentação oficial possui mais detalhes.

Testes Assíncronos com Promises

Algo muito comum em JavaScript é testar funções assícronas. Por exemplo, digamos que você tenha a seguinte função:

export function waitSeconds(seconds: number): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`waited ${seconds} seconds`);
    }, seconds * 1000);
  });
}
Enter fullscreen mode Exit fullscreen mode

Basicamente essa é uma função que aguarda alguns segundos e retorna uma mensagem. Ela tem como parâmetro um número que represente a quantidade de segundos e retorna uma Promise.

Você pode testar isso de várias maneiras, mas eu separei quatro tipos de testes para esta função:

import { waitSeconds } from '../src/index';

describe('example of asynchronous testing', () => {
  test('testing with async/await', async () => {
    expect(await waitSeconds(1)).toBe('waited 1 seconds');
  });

  test('testing returning a promise', () => {
    return expect(waitSeconds(1.5)).resolves.toBe('waited 1.5 seconds');
  });

  test('testing returning a promise with callback function', () => {
    return waitSeconds(0.5).then((response) => {
      expect(response).toBe('waited 0.5 seconds');
    });
  });

  test('testing with callback function', (done) => {
    waitSeconds(0.8).then((response) => {
      expect(response).toBe('waited 0.8 seconds');
      done();
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

Vale destacar que embora sejam quatro tipos diferentes de testes, o resultado deles é o mesmo e você pode escolher o que for mais conveniente para seu caso. Na documentação oficial é mencionado sobre testes assíncronos

Fontes onde pesquisei esse conteúdo:

Top comments (0)