Henrique Couto

Engenheiro de software frontend

profile picture

Testes unitários no Next com Jest

Testes unitários são muito úteis para garantir que nossos componentes continuem funcionando quando realizarmos manutenções no futuro.

Instalando dependências

Para configurar o Jest vamos instalar pacotes jest, @testing-library/react e @testing-library/jest-dom:

1yarn add -D jest @testing-library/react @testing-library/jest-dom

Configurando o testes

É necessário criar um arquivo de configuração para que o Jest entenda como realizar os testes.

Crie um arquivo jest.config.js na raíz do seu projeto:

1const nextJest = require('next/jest')
2
3const createJestConfig = nextJest({
4  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
5  dir: './',
6})
7
8// Add any custom config to be passed to Jest
9const customJestConfig = {
10  // Add more setup options before each test is run
11  // setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
12  // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
13  moduleDirectories: ['node_modules', '<rootDir>/'],
14  testEnvironment: 'jest-environment-jsdom',
15}
16
17// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
18module.exports = createJestConfig(customJestConfig)

Agora, basta adicionar um script para executar os testes no package.json:

1{
2 ...
3 "scripts": {
4    ...
5    "test": "jest --watch"
6  },
7 ...
8}

Criando nossos testes

Para esse exemplo, vamos criar o primeiro teste do componente GetInTouch (da página principal aqui do blog).

O componente possui um título e alguns botões que redirecionam para meu perfil em outros sites. Vamos testar se o título aparece corretamente.

Primeiro é necessário realizar um mock do hook de internacionalização, responsável por traduzir os textos do blog.

1import { useIntl } from "../../hooks/useIntl";
2
3const TITLE = "GET IN TOUCH";
4jest.mock("../../hooks/useIntl");
5
6describe("Get In Touch Component", () => {
7  beforeAll(() => {
8    (useIntl as jest.Mock).mockImplementation(() => ({
9      getInTouch: { title: TITLE },
10    }));
11  });
12});

Para testar se a string da variável TITLE está sendo exibida corretamente, podemos utilizar a função queryByText e utilizar o expect para garantir que está tudo ok:

1  test("should render get-in-touch title", () => {
2    const { queryByText } = render(<GetInTouch />);
3
4    expect(queryByText(TITLE)).toBeTruthy();
5  });

Além do queryByText outros métodos estão disponíveis e é possível encontrar a descrição para eles na documentação da testing library

No fim, nosso arquivo de teste ficará da seguinte forma:

1import { render } from "@testing-library/react";
2import { useIntl } from "../../hooks/useIntl";
3import { GetInTouch } from ".";
4import { ThemeProvider } from "styled-components";
5import { darkTheme } from "../../styles/themes/dark-theme";
6
7const TITLE = "GET IN TOUCH";
8
9jest.mock("../../hooks/useIntl");
10
11describe("Get In Touch Component", () => {
12  beforeAll(() => {
13    (useIntl as jest.Mock).mockImplementation(() => ({
14      getInTouch: { title: TITLE },
15    }));
16  });
17
18  test("should render get-in-touch title", () => {
19    const { queryByText } = render(<GetInTouch />);
20
21    expect(queryByText(TITLE)).toBeTruthy();
22  });
23});

Rodando yarn test podemos ver que o teste passou:

test pass

Para ter certeza que está tudo ok, podemos substituir o expect(queryByText(TITLE)).toBeTruthy(); por expect(queryByText(TITLE)).toBeFalsy();

test fail

That's it!