Context API React: o que é, como funciona e como criar testes unitários

Vinicios Neves
Vinicios Neves

Compartilhe

Avalie este artigo

5 minutos de leitura

Olá! Tudo certo por aí? 

Neste artigo, vamos abordar como utilizar a Context API em conjunto com testes unitários para garantir o correto funcionamento de aplicações em React. Para facilitar, utilizaremos como exemplo prático uma lista de tarefas (ToDo list). 

Antes de começarmos, é importante lembrar que a Context API é uma solução criada para resolver o prop drilling no React, problema comum quando precisamos passar muitos dados entre componentes aninhados.

Banner da Alura convidando profissionais a desenvolver habilidades em inteligência artificial para acompanhar as transformações do mercado de tecnologia. A campanha destaca que quem utiliza IA produz mais, cresce na carreira e se torna mais competitivo, reforçando que a inteligência artificial deixou de ser tendência e passou a ser uma habilidade essencial. O banner incentiva a começar a aprender IA com os cursos da Alura e impulsionar a transformação digital.

Se você está se perguntando "Context API no React: o que é?", trata-se de um recurso nativo do React para compartilhamento de estado global entre componentes, sem a necessidade de passar props manualmente

Primeiro, vamos criar o nosso Provider de contexto. O Provider irá fornecer os dados para os componentes que estiverem "subscritos" a ele. Veja um exemplo básico: 

import React, { useState } from "react"; 
export const TodoContext = React.createContext(); 
export function TodoProvider(props) { 
  const [todos, setTodos] = useState([]); 
  function addTodo(todo) { 
    setTodos([...todos, todo]); 
  } 
  function deleteTodo(index) { 
    setTodos(todos.filter((todo, i) => i !== index)); 
  } 
  return ( 
<TodoContext.Provider 
   value={{ 
        todos, 
        addTodo, 
        deleteTodo, 
   }} 
> 
   {props.children} 
</TodoContext.Provider> 
  ); 
}

No exemplo anterior, criamos um Provider que armazena uma lista de tarefas (todos) e disponibiliza duas funções: uma para adicionar e outra para remover tarefas da lista. 

Agora que temos o nosso Provider, vamos criar os nossos testes unitários. Para isso, vamos usar o pacote @testing-library/react

O primeiro teste será para verificar se a função addTodo está adicionando corretamente uma tarefa à lista. Tipo assim: 

import { render, fireEvent, wait } from "react-testing-library"; 
import { TodoProvider, TodoContext } from "./TodoProvider"; 
test("adiciona uma tarefa à lista", async () => { 
  const { getByTestId, getByText } = render( 
<TodoProvider> 
   <TodoContext.Consumer> 
     {({ addTodo }) => ( 
       <button data-testid="add-button" onClick={() => addTodo("nova tarefa")}> 
            Adicionar tarefa 
       </button> 
     )} 
   </TodoContext.Consumer> 
</TodoProvider> 
  ); 
  fireEvent.click(getByTestId("add-button")); 
  await wait(() => expect(getByText("nova tarefa")).toBeInTheDocument()); 
});

No exemplo acima, renderizamos o Provider e o Consumer em um wrapper e clicamos no botão "Remover". Em seguida, utilizamos a função de espera, "wait", da biblioteca de testes para garantir que o elemento com o texto "tarefa 1" tenha sido removido. 

O segundo teste será para verificar se a função deleteTodo está removendo corretamente uma tarefa da lista. Aqui está como podemos fazer isso: 

import { render, fireEvent, wait } from "react-testing-library"; 
import { TodoProvider, TodoContext } from "./TodoProvider"; 
test("remove uma tarefa da lista", async () => { 
  const { getByTestId, queryByText } = render( 
<TodoProvider> 
   <TodoContext.Consumer> 
     {({ todos, deleteTodo }) => 
          todos.map((todo, index) => ( 
         <div key={todo}> 
           <span>{todo}</span> 
           <button data-testid="delete-button" onClick={() => deleteTodo(index)}> 
             Remover 
           </button> 
         </div> 
       )) 
     } 
   </TodoContext.Consumer> 
</TodoProvider> 
  ); 
  fireEvent.click(getByTestId("delete-button")); 
  await wait(() => expect(queryByText("tarefa 1")).toBeNull()); 
});

No exemplo acima, estamos renderizando o Provider e o Consumer dentro de um wrapper e, em seguida, clicando no botão "Remover". Depois, estamos usando a função "wait" do "react-testing-library" para garantir que o elemento com o texto "tarefa 1" não esteja sendo exibido antes de verificarmos se ele é nulo. 

Agora que já vimos como criar testes unitários para Context API React usando React Testing Library, vale reforçar os principais benefícios de aplicar testes unitários em sua aplicação React. 

Testes unitários nos ajudam a garantir que o código da nossa aplicação esteja funcionando corretamente, mesmo quando fazemos alterações futuras.

Isso nos permite ter mais confiança no código que estamos escrevendo e nos dá a segurança de saber que as alterações que estamos fazendo não estão quebrando o funcionamento de outras partes da aplicação. 

Além disso, escrever testes unitários contribui para um código mais limpo e fácil de manter, porque incentiva a divisão do código em partes menores e mais fáceis de testar. Isso evita a criação de funções muito longas e complexas. 

O pacote react-testing-library é uma ótima opção para fazer testes em aplicações React, pois ele nos permite testar o comportamento do usuário, como clicar em botões e preencher formulários, de maneira mais fácil e intuitiva.  

Além disso, ele nos ajuda a escrever testes mais robustos, pois não se prende a detalhes de implementação, o que nos permite alterar o código sem precisar alterar os testes. 

Se você deseja se aprofundar em Context API React, aprender mais sobre testes unitários React com React Testing Library, praticar contexto React ou resolver de vez o prop drilling React em seus projetos, confira as sugestões abaixo da Alura: 

Esperamos que este artigo tenha esclarecido como utilizar e testar a Context API em uma aplicação React. Lembre-se de sempre testar o código para garantir seu correto funcionamento e facilitar a manutenção futura. 

Até a próxima 🖖! 

Avalie este artigo

Vinicios Neves
Vinicios Neves

Vinicios Neves, Tech Lead e Educador, mistura código e didática há mais de uma década. Especialista em TypeScript, lidera equipes full-stack em Portugal e inspira futuros desenvolvedores na FIAP e Alura. Com um pé no código e outro no ensino, ele prova que a verdadeira engenharia de software vai além das linhas de código. Além de, claro, ser senior em falar que depende.

Veja outros artigos sobre Front-end

Estude 2 anos por R$ 158/mês. Planos com até 35% OFF. Ver planos.