Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: testes de integração e mocks no Front-end

React: testes de integração e mocks no Front-end

Testando rotas da aplicação - Apresentação

Boas-vindas! Sou Neilton Seguins e serei seu instrutor ao longo deste curso de React, em que aprenderemos sobre testes de integração e mocks.

Autodescrição: sou um homem negro com cabelos curtos, pretos e encaracolados. Tenho olhos castanhos e estou usando óculos de grau com armação retangular. Estou vestindo uma camiseta azul escura. Ao fundo, há uma parede com iluminação azul e rosa.

Este curso é para você que tem curiosidade de saber como testar:

Neste curso, vamos testar a aplicação do Bytebank. O time de desenvolvimento evoluiu nosso projeto, inserindo novas rotas e adicionando a conexão com uma API. A nível de código, há muitas novidades também!

Se você não tem familiaridade com o projeto do Bytebank, recomendamos que você assista ao curso de React JS: testes automatizados no front-end. Nele, você conhecerá o projeto Bytebank, enquanto aprende sobre os diferentes tipos de testes, bem como as vantagens de realizar testes!

Animado para estudar? Vamos lá!

Testando rotas da aplicação - Testando a rota principal

A aplicação do Bytebank cresceu! O time de desenvolvimento utilizou a biblioteca React Router Dom e, agora, podemos acessar novas rotas. No menu da lateral esquerda da aplicação, temos os seguintes links:

Ao clicar em cada um deles, a página correspondente aparecerá na parte inferior central da tela.

Configurações de rotas

Dado que temos novas funcionalidades, vamos desenvolver testes para garantir que elas estão funcionando como esperado. Primeiramente, vamos abrir nosso projeto no VS Code.

Na pasta "src", abriremos o arquivo routes.js, em que temos as configurações de rotas da nossa aplicação:

import { Route, Routes } from 'react-router-dom';
import Cartoes from './componentes/Cartoes';
import Investimentos from './componentes/Investimentos';
import Servicos from './componentes/Servicos';
import Pagina404 from './paginas/Pagina404';
import App from './paginas/Principal/App';

export default function AppRoutes() {
  return (
    <Routes>
      <Route path="/" element={<App />}>
        <Route path="cartoes" element={<Cartoes />} />
        <Route path="investimentos" element={<Investimentos />} />
        <Route path="servicos" element={<Servicos />} />
      </Route>
      <Route path="*" element={<Pagina404 />} />
    </Routes>
  );
}

Assim, quando estamos na rota principal (apenas /), o componente App é renderizado. Quando estamos na rota cartoes, renderizamos Cartoes, e assim em diante. Caso estejamos em uma rota que não existe na aplicação, vamos renderizar uma página 404.

Teste da rota principal

Então, nosso primeiro teste será responsável por verificar se o React Router Dom nos direciona para a rota principal quando usarmos o caminho /.

Na pasta "src", vamos criar um arquivo chamado routes.test.js. De início, importaremos o render e o screen de @testing-library/react. Em seguida, importaremos nosso componente App:

import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';

Na sequência, vamos usar a função describe(). No primeiro parâmetro, a descrição será simplesmente "Rotas". No segundo parâmetro, passaremos uma função callback:

import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';

describe('Rotas', () => {

});

Dentro da função callback de describe(), vamos desenvolver nosso teste com a função test(). No primeiro parâmetro, a descrição do teste será "Deve renderizar a rota principal". No segundo parâmetro, passaremos outra função callback:

import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';

describe('Rotas', () => {
  test('Deve renderizar a rota principal', () => {

  });
});

Dentro dessa função callback, vamos renderizar o componente App. Depois, faremos uma consulta. Declararemos uma constante chamada usuario e utilizaremos o método getByText() para encontrar a mensagem de boas-vindas que aparece na parte superior central da aplicação, isto é, o texto "Olá, Joana :)!":

import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';

describe('Rotas', () => {
  test('Deve renderizar a rota principal', () => {
    render(<App />);
    const usuario = screen.getByText('Olá, Joana :)!');
  });
});

Vale lembrar que usamos aspas simples, ao indicar o texto a ser encontrado com getByText().

Em seguida, utilizaremos o expect() junto do toBeInTheDocument() para indicar que esperamos a pessoa usuária esteja no documento:

import { render, screen } from '@testing-library/react';
import App from './paginas/Principal/App';

describe('Rotas', () => {
  test('Deve renderizar a rota principal', () => {
    render(<App />);
    const usuario = screen.getByText('Olá, Joana :)!');
    expect(usuario).toBeInTheDocument();
  });
});

Após salvar o arquivo, vamos abrir o terminal com o atalho "Ctrl + J" e executar nosso script de testes:

npm run test

Como resultado, descobrimos que um teste falhou. No terminal, temos uma mensagem de erro indicando que useLocation() somente pode ser usado no contexto de um componente <Router>:

useLocation() may be used only in the context of a component.

Em "src > paginas > Principal", no arquivo App.js, utilizamos o useLocation() na linha 18. Esse hook do React Router Dom só pode ser usado dentro de uma rota.

Voltando ao arquivo routes.js, notamos que fizemos a configuração correta e o App está dentro de um <Routes>. Então, o que está acontecendo de errado?

O Jest não consegue acessar a pilha do histórico do navegador, de modo que não compreende que estamos em um contexto de rota. Como solução, podemos usar um componente do React Router Dom chamado Browser Router. Ele nos permitirá manipular o histórico de navegação.

Vamos voltar ao arquivo routes.test.js para implementar essa alteração, passando um novo parâmetro para render(). Vamos usar um wrapper, que funciona como um envelope, um elemento que envolverá o componente App. No caso, será um BrowserRouter:

import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import App from './paginas/Principal/App';

describe('Rotas', () => {
  test('Deve renderizar a rota principal', () => {
    render(<App />, { wrapper: BrowserRouter });
    const usuario = screen.getByText('Olá, Joana :)!');
    expect(usuario).toBeInTheDocument();
  });
});

Note que, ao adicionar o BrowserRouter, o VS Code automaticamente adiciona a importação correspondente no início do arquivo, na linha 2.

Essa modificação deve ser o suficiente para resolver o problema que tivemos. Vamos salvar o arquivo e executar o testes novamente. Dessa vez, os testes passarão.

Será que precisaremos usar o Browser Router toda vez que quisermos acessar uma rota? Existem outras maneiras de resolver essa situação, vamos explorá-las a seguir.

Testando rotas da aplicação - Controlando o histórico

Aprendemos como controlar a pilha do histórico de navegações, utilizando o Browser Router para testar a rota principal da nossa aplicação.

Contudo, o Browser Router não permite o acesso a outras rotas livremente, então não temos um controle maior da pilha do histórico de navegações. A boa notícia é que existe outro componente do React Router Dom que permite esse acesso. Trata-se do Memory Router.

Teste da rota de cartões

Com o projeto aberto no VS Code, vamos acessar a pasta "src", abrir o arquivo routes.test.js e começar a desenvolver um novo teste para testar a rota para a página de cartões.

Novamente usaremos a função test(). No primeiro parâmetro, a descrição será "Deve renderizar a rota Cartões". No segundo parâmetro, passaremos uma arrow function:

import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import App from './paginas/Principal/App';

describe('Rotas', () => {
  test('Deve renderizar a rota principal', () => {
    render(<App />, { wrapper: BrowserRouter });
    const usuario = screen.getByText('Olá, Joana :)!');
    expect(usuario).toBeInTheDocument();
  });

  test('Deve renderizar a rota Cartões', () => {

  });
});

Como pretendemos renderizar os componentes Cartoes e MemoryRouter, vamos importá-los no início do arquivo. Para auxiliar na criação dos testes, também será necessário importar Routes e Route de react-router-dom:

import { render, screen } from '@testing-library/react';
import { BrowserRouter, MemoryRouter, Routes, Route } from 'react-router-dom';
import App from './paginas/Principal/App';
import Cartoes from './componentes/Cartoes';

describe('Rotas', () => {
  test('Deve renderizar a rota principal', () => {
    render(<App />, { wrapper: BrowserRouter });
    const usuario = screen.getByText('Olá, Joana :)!');
    expect(usuario).toBeInTheDocument();
  });

  test('Deve renderizar a rota Cartões', () => {

  });
});

Dentro da função callback, em vez de simplesmente renderizar o componente Cartoes, vamos renderizar o <MemoryRouter>:

// código anterior omitido

  test('Deve renderizar a rota Cartões', () => {
    render(
        <MemoryRouter>

        </MemoryRouter>
    );
  });
});

Dentro do <MemoryRouter>, usaremos uma sintaxe semelhante à definição de rotas da aplicação. Colocaremos o <Routes> e, dentro dele, o <Route>:

// ...

  test('Deve renderizar a rota Cartões', () => {
    render(
        <MemoryRouter>
            <Routes>
                <Route></Route>
            </Routes>

        </MemoryRouter>
    );
  });
});

O <Route> terá a propriedade path com a rota principal / e a propriedade element com o componente App:

// ...

  test('Deve renderizar a rota Cartões', () => {
    render(
        <MemoryRouter>
            <Routes>
                <Route path="/" element={<App />}></Route>
            </Routes>
        </MemoryRouter>
    );
  });
});

Dentro do Route do elemento App, vamos definir uma rota-filha. O path dela será cartoes e o elemento será o componente de cartões:

// ...

  test('Deve renderizar a rota Cartões', () => {
    render(
        <MemoryRouter>
            <Routes>
                <Route path="/" element={<App />}>
                <Route path="cartoes" element={<Cartoes />} />
                </Route>
            </Routes>
        </MemoryRouter>
    );
  });
});

O MemoryRouter precisa receber uma props chamada initialEntries, que são as entradas principais, passadas em um formato parecido com um array.

Antes do método render(), vamos definir a constante rota, que receberá o caminho para a rota de cartões. Em seguida, passaremos essa constante na propriedade initialEntries do MemoryRouter:

// ...

  test('Deve renderizar a rota Cartões', () => {
    const rota = '/cartoes';
    render(
        <MemoryRouter initialEntries={[rota]}>
            <Routes>
                <Route path="/" element={<App />}>
                <Route path="cartoes" element={<Cartoes />} />
                </Route>
            </Routes>
        </MemoryRouter>
    );
  });
});

Após o render(), definiremos uma variável chamada meusCartoes, que armazenará o resultado da consulta. Usaremos o método getByText(), passando como parâmetro a string "Meus cartões" — isto é, o título do componente:

// ...

  test('Deve renderizar a rota Cartões', () => {
    const rota = '/cartoes';
    render(
        <MemoryRouter initialEntries={[rota]}>
            <Routes>
                <Route path="/" element={<App />}>
                <Route path="cartoes" element={<Cartoes />} />
                </Route>
            </Routes>
        </MemoryRouter>
    );

    const meusCartoes = screen.getByText('Meus cartões');
  });
});

Por fim, vamos indicar o resultado esperado. Nós esperamos que o conteúdo textual de meusCartoes seja "Meus cartões", que é exatamente o título do componente:

// ...

  test('Deve renderizar a rota Cartões', () => {
    const rota = '/cartoes';
    render(
        <MemoryRouter initialEntries={[rota]}>
            <Routes>
                <Route path="/" element={<App />}>
                <Route path="cartoes" element={<Cartoes />} />
                </Route>
            </Routes>
        </MemoryRouter>
    );

    const meusCartoes = screen.getByText('Meus cartões');
    expect(meusCartoes).toHaveTextContent('Meus cartões');
  });
});

Após salvar o arquivo, abriremos o terminal ("Ctrl + J") e executaremos os testes. Podemos rodar tanto o comando npm run test quanto o npm test, pois o Node compreende ambos:

npm test

Os testes passarão, sem problemas.

Agora, sabemos que existem diferentes alternativas para controlar as rotas de uma aplicação. O Browser Router e o Memory Router são algumas opções. Assim, temos mais possibilidades para o desenvolvimento de testes melhores para rotas.

Na sequência, testaremos um componente que usa o useLocation(), um hook do React Router Dom!

Sobre o curso React: testes de integração e mocks no Front-end

O curso React: testes de integração e mocks no Front-end possui 93 minutos de vídeos, em um total de 46 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda React acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri, a inteligência artificial da Alura

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas