devly
Voltar para Testes de Software

Mão na Massa: Seus Primeiros Testes Unitários (e o Truque dos Mocks!)

Escrevendo testes unitários básicos, usando Jest como exemplo, e entendendo Mocks/Stubs.

Atualizado em: 27 de Maio, 2025
Notas do Autor

E aí, Dev! Chegou a hora de sujar as mãos (ou melhor, o teclado!) com testes. Nas aulas anteriores, a gente conversou sobre a importância de testar, desvendou a estratégia da Pirâmide e entendeu a mentalidade TDD/BDD. Tudo muito legal na teoria, né? Mas eu sei que a dúvida que fica é: "Beleza, Gabs, mas como eu escrevo essa bagaça na prática?".

Lembro da minha primeira vez escrevendo um teste unitário 'de verdade'. Parecia que eu tava escrevendo mais código pro teste do que pra função! E quando apareceu um negócio que falava com API? Quase desisti. 'Como eu testo isso sem chamar a API toda hora?!'. Foi aí que os Mocks entraram e... click. Entendi o poder de isolar as coisas.

É esse 'click' que quero te ajudar a ter hoje. Vamos pegar um exemplo simples, usando Jest (uma ferramenta super popular no mundo JavaScript), e desmistificar como escrever seus primeiros testes unitários e como usar "dublês" (Mocks/Stubs) pra lidar com dependências. Não é bicho de sete cabeças, prometo!


1. Preparando o Terreno: Por Que um Framework (Ex: Jest)?

Você até poderia escrever testes sem nenhuma ferramenta, mas seria como construir uma casa sem martelo e serrote: muito mais difícil e demorado. Frameworks de teste como Jest, PyTest (Python), RSpec (Ruby), JUnit (Java), etc., te dão:

Test Runner: Um programa que encontra e executa seus testes.
Assertion Library: Funções pra verificar se o resultado do seu código é o esperado (Ex: expect(resultado).toBe(10)).
Mocking/Stubbing: Ferramentas para criar os "dublês" que falamos.
Relatórios: Mostram quais testes passaram, quais falharam e por quê.

Nesta aula, usaremos Jest como exemplo, mas os conceitos valem para qualquer framework.


2. Anatomia de um Teste Unitário Simples (com Jest)

Vamos começar com o mais básico do básico: testar uma função de soma.

O Código (Sua "Unidade"):

javascript
// arquivo: calculadora.js
function soma(a, b) {
  return a + b;
}

module.exports = soma; // Exporta a função para poder ser usada no teste

O Teste (Verificando a Unidade):

javascript
// arquivo: calculadora.test.js
const soma = require('./calculadora'); // Importa a função a ser testada

describe('Calculadora - Função Soma', () => {
  // 'describe' agrupa testes relacionados. É como um capítulo.

  it('deve somar 2 + 2 e retornar 4', () => {
    // 'it' (ou 'test') define um caso de teste específico.
    const resultado = soma(2, 2); // 1. Executa a função
    expect(resultado).toBe(4);   // 2. Verifica (Assert) se o resultado é o esperado
  });

  it('deve somar números negativos corretamente', () => {
    const resultado = soma(-5, 3);
    expect(resultado).toBe(-2);
  });
});

Descomplicando:

describe: Agrupa testes com um tema comum. Ajuda na organização.
it ou test: Descreve o que *um* teste específico deve fazer. A descrição deve ser clara!
expect: É a função de asserção. Você "espera" que algo (resultado) seja (.toBe()) alguma coisa (4). O .toBe() é um matcher – existem vários outros (ex: .toEqual(), .toBeTruthy(), .toContain()).

Simples, né? Isso é um teste unitário. Ele testa apenas a função soma, de forma isolada.


3. O Problema: E Quando a Unidade Não Está Sozinha?

Raramente nossas funções são tão simples. Elas conversam com bancos de dados, chamam APIs externas, leem arquivos, usam outros módulos... Essas são as dependências.

Se o seu teste unitário realmente chama uma API externa ou acessa um banco de dados, ele deixa de ser puramente unitário. Por quê?

Lentidão: Chamar API/DB é lento. Milhares de testes lentos = suíte de testes inútil.
Dependência Externa: Se a API estiver fora do ar, seu teste vai falhar, *mesmo que seu código esteja certo*.
Isolamento Quebrado: Você não está testando *só* sua unidade, mas também a API, o banco, a rede...

Como resolver isso? Com a mágica dos Mocks e Stubs!


4. Mocks & Stubs: Os Dublês do Seu Código

Pense em Mocks e Stubs como atores dublês. Eles entram em cena para substituir as dependências reais, permitindo que você teste sua unidade de forma isolada e previsível.

Stub: Um dublê simples. Ele só existe pra retornar um valor pré-definido quando é chamado. Não se importa como ou quantas vezes foi chamado.
Mock: Um dublê mais inteligente. Além de poder retornar valores, ele grava como foi interagido. Você pode verificar se ele foi chamado, quantas vezes, com quais parâmetros. É útil pra testar interações.

Exemplo Prático (com Jest - Mocking uma API):

Imagine uma função que busca dados de um usuário numa API:

O Código (com dependência):

javascript
// arquivo: userService.js
const axios = require('axios'); // Dependência externa (HTTP client)

async function buscarUsuario(userId) {
  try {
    const response = await axios.get(`https://api.exemplo.com/users/${userId}`);
    return response.data;
  } catch (error) {
    console.error("Erro ao buscar usuário:", error);
    return null;
  }
}

module.exports = { buscarUsuario };

O Teste (com Mock):

javascript
// arquivo: userService.test.js
const axios = require('axios');
const { buscarUsuario } = require('./userService');

jest.mock('axios'); // 1. Diz ao Jest: "Ei, quando alguém pedir 'axios', entregue um dublê!"

describe('UserService - buscarUsuario', () => {
  it('deve retornar os dados do usuário quando a API responde com sucesso', async () => {
    const dadosUsuarioMock = { id: 1, name: 'Devly User' };

    // 2. Configura o dublê: "Quando o 'get' do axios for chamado, finja que
    //    a API respondeu com sucesso e retorne estes dados"
    axios.get.mockResolvedValue({ data: dadosUsuarioMock });

    const usuario = await buscarUsuario(1); // 3. Chama a função (que usará o 'axios' mockado)

    // 4. Verifica se a função retornou o que o dublê prometeu
    expect(usuario).toEqual(dadosUsuarioMock);
    // 5. (Opcional) Verifica se o dublê foi chamado do jeito certo
    expect(axios.get).toHaveBeenCalledWith('https://api.exemplo.com/users/1');
  });

  it('deve retornar null quando a API responde com erro', async () => {
      // Configura o dublê para simular um erro
      axios.get.mockRejectedValue(new Error('API fora do ar'));

      const usuario = await buscarUsuario(2);

      expect(usuario).toBeNull();
  });
});

O Pulo do Gato: Percebeu? Nós testamos a buscarUsuario sem nunca chamar a API de verdade! Usamos o jest.mock('axios') para interceptar a chamada e o mockResolvedValue / mockRejectedValue para dizer ao dublê o que fazer. Isso é isolar a unidade e garantir um teste rápido e previsível.


5. O Mínimo Viável Que Abre Portas

Você não precisa ser um mestre em todos os tipos de mocks e frameworks amanhã. Mas entender o que é um teste unitário, saber escrever testes básicos para suas funções (especialmente as de lógica pura) e, crucialmente, entender o conceito de mocks para isolar dependências... isso já te coloca MUITO à frente de muitos devs.

É esse "mínimo viável" que as empresas gringas esperam ver. É o sinal de que você entende a importância da qualidade e sabe usar as ferramentas básicas para alcançá-la.


💊 Pílula Devly

Seu primeiro teste não precisa ser genial, só precisa existir. Comece simples, isole o que não é seu (mocks!), e construa confiança um expect de cada vez. Cada teste verde é um passo a mais rumo a um código robusto (e ao seu salário em dólar!).

Anterior

TDD/BDD: A Mentalidade "Pense Antes de Codar"

Voltar

Próximo

Mostrando Suas Skills de Teste (CV, GitHub e Entrevistas)

Continuar