---
title: "Excessive Mocking"
type: "test-smell"
slug: "excessive-mocking"
url: "http://localhost:3000/pt-br/test-smells/excessive-mocking.md"
category: "Maus Cheiros de Mocking"
description: "Um teste configura tantos objetos mock e interações stubadas que a configuração dos mocks ofusca a verificação propriamente dita, então o teste acaba exercitando os mocks em vez do comportamento real."
---
# Excessive Mocking

> Um teste configura tantos objetos mock e interações stubadas que a configuração dos mocks ofusca a verificação propriamente dita, então o teste acaba exercitando os mocks em vez do comportamento real.

## Signs and Symptoms

Um teste é majoritariamente _arrange_: longos blocos de criação de mocks, linhas de `when(...).thenReturn(...)` / `mockReturnValue(...)` e `verify(...)`, com pouco código real sob teste. Sinais reveladores:

* **Mais encanamento de mocks do que asserções.** A configuração tem muitas linhas; o "act" é uma única chamada; o "assert" verifica que os mocks foram _chamados_ em vez de que um resultado está correto.
* **Mockar coisas que são suas.** Objetos de domínio, objetos de valor ou colaboradores de lógica pura são mockados em vez de apenas as fronteiras externas (rede, banco, relógio, sistema de arquivos, terceiros).
* **Cadeias de mocks / "train wrecks".** Um mock retorna outro mock que retorna outro mock, espelhando o grafo de chamadas de produção.
* **Verificação só de interação.** O teste faz asserções `toHaveBeenCalledWith(...)` em cada colaborador e nunca verifica o valor retornado ou o estado resultante.
* **Frágil em refatorações.** Reordenar chamadas internas ou extrair um método quebra muitos testes mesmo que o comportamento permaneça inalterado.
* **Cinco ou mais mocks só para instanciar o SUT** — normalmente um sinal de que o próprio SUT tem dependências demais.

```js
test('places order', () => {
  const inventory = { check: jest.fn().mockReturnValue(true) };
  const pricing   = { quote: jest.fn().mockReturnValue(42) };
  const tax       = { calc:  jest.fn().mockReturnValue(4.2) };
  const wallet    = { charge: jest.fn().mockReturnValue({ ok: true }) };
  const ledger    = { record: jest.fn() };
  const emailer   = { send: jest.fn() };
  const audit     = { log: jest.fn() };
  const clock     = { now: jest.fn().mockReturnValue(0) };

  const svc = new OrderService(inventory, pricing, tax, wallet, ledger, emailer, audit, clock);
  svc.place(cart);

  // verifica que os mocks foram chamados — não que o pedido está correto
  expect(inventory.check).toHaveBeenCalled();
  expect(pricing.quote).toHaveBeenCalled();
  expect(wallet.charge).toHaveBeenCalledWith(46.2);
  expect(ledger.record).toHaveBeenCalled();
});

```

## Reasons for the Problem

**Por que acontece**

* **O SUT tem colaboradores demais.** Mocking excessivo costuma ser um sinal de _design_: uma classe com baixa coesão e muitas dependências força cada teste a montar todas elas. Como diz a literatura do catálogo, _"se você precisa mockar cinco classes internas só para testar um método, o método tem dependências demais — isso é um problema de design, não de teste."_
* **Hábito / reflexo de "mockar tudo".** Levar o teste baseado em interação ("escola de Londres") ao extremo, ou mockar por reflexo para evitar tocar em um banco ou na rede, leva a mockar lógica pura que poderia ser testada diretamente.
* **Objetos reais difíceis de construir.** Quando colaboradores reais são complicados de instanciar, um mock parece mais fácil do que consertar o construtor ou adicionar um fake.

**Por que prejudica**

* **Falsa confiança.** Mocks codificam _as suas suposições_ sobre uma dependência. Se a implementação real divergir, o teste continua passando — por exemplo, um stub que afirma que `sum()` retorna apenas inteiros positivos mantém o teste verde mesmo depois que o método real muda. Tais testes podem se tornar tautológicos: eles só verificam que os mocks que você escreveu se comportam como os mocks que você escreveu. Como alerta a própria documentação do Mockito, _"se tudo está mockado, estamos realmente testando o código de produção?"_
* **Fragilidade / alta manutenção.** Verificar chamadas específicas trata detalhes de implementação como o contrato, então refatorações inofensivas (ordem das chamadas, helpers extraídos) quebram os testes. Isso é o _Overspecified Software_ / _Fragile Test_ de Meszaros.
* **Baixa legibilidade.** Centenas de linhas de configuração de dependências enterram a única coisa de que o teste trata, muito parecido com um _Mystery Guest_ — um revisor não consegue dizer qual comportamento é de fato verificado.
* **Bugs de integração que passam batido.** A ligação real entre os componentes nunca é exercitada; os bugs vivem exatamente nas costuras que os mocks substituíram. Alta cobertura mascara baixa qualidade.

## Treatment

Trate o uso pesado de mocks como feedback e, então, reduza a _necessidade_ de mockar:

1. **Conserte o design primeiro.** Se você precisa mockar mais de 5 colaboradores para construir o SUT, divida responsabilidades ou reduza as dependências do construtor. Menos dependências reais significa menos mocks.
2. **Mocke apenas nas fronteiras da arquitetura.** Mocke as coisas que _não são suas_ (rede, banco, relógio, sistema de arquivos, APIs de terceiros); use **instâncias reais** dos seus próprios objetos de domínio e de valor.
3. **Extraia um núcleo puro (functional core / imperative shell).** Mova a lógica de cálculo/decisão para fora da classe pesada em I/O para que ela possa ser testada com **zero mocks**, deixando uma casca fina que precisa de apenas um ou dois dublês de fronteira.
4. **Prefira verificação de estado em vez de verificação de interação.** Verifique o valor retornado ou o estado resultante em vez de `verify(...)`/`toHaveBeenCalledWith(...)` em cada colaborador. Reserve as verificações de interação para o único efeito colateral que realmente importa.
5. **Use o dublê mais simples que funcione.** Substitua mocks elaborados por **stubs** (apenas retornam valores) ou por um único **fake em memória** reutilizável em vez de re-stubar cada método a cada teste.
6. **Revele o excesso de mocks dinamicamente.** Habilitar o strict stubbing do Mockito (o padrão `MockitoExtension`/`MockitoJUnitRunner`) lança `UnnecessaryStubbingException` para stubs que são configurados mas nunca usados — uma forma barata de encontrar mocks de que você não precisava.

```js
// ANTES: 8 mocks, verificando chamadas
const pricing = { quote: jest.fn().mockReturnValue(42) };
const tax     = { calc:  jest.fn().mockReturnValue(4.2) };
// + mais 6 mocks ...
expect(wallet.charge).toHaveBeenCalledWith(46.2);

// DEPOIS: lógica pura testada diretamente — sem mocks
expect(totalFor(cart, rates)).toBe(46.2);

// apenas a fronteira real é falseada; verifique o estado, não as chamadas
const wallet = new InMemoryWallet({ balance: 100 });
const svc = new OrderService(new InMemoryInventory(cart), wallet);
const order = svc.place(cart);
expect(order.total).toBe(46.2);
expect(wallet.balance).toBe(53.8);

```
