---
title: "Apenas Para Testadores"
type: "test-smell"
slug: "for-testers-only"
url: "http://localhost:3000/pt-br/test-smells/for-testers-only.md"
category: "Maus Cheiros de Acoplamento"
description: "O código de produção contém métodos, acessadores de estado ou seams (costuras) que existem apenas para serem usados pelos testes, poluindo a API real e convidando a testes que verificam detalhes internos em vez do comportamento."
---
# Apenas Para Testadores

> O código de produção contém métodos, acessadores de estado ou seams (costuras) que existem apenas para serem usados pelos testes, poluindo a API real e convidando a testes que verificam detalhes internos em vez do comportamento.

## Signs and Symptoms

Você encontra membros no código de **produção** cujos únicos chamadores vivem em arquivos de teste. Sinais reveladores:

* Métodos, getters/setters, exports ou parâmetros de construtor usados exclusivamente a partir de `*.test.ts` / `*.spec.ts`.
* Nomes ou marcadores com cara de teste: `getStateForTest`, `resetForTesting`, `__getInternal`, `FTO_*`, `forTest`, comentários como `// only used by tests`, ou anotações como `@VisibleForTesting` / `@TestOnly` / `@internal`.
* Visibilidade relaxada (um campo tornado `public`/exportado, um `#private` transformado em `protected`) puramente para que um teste consiga alcançar o estado interno.
* "Seams" extras — um `setClock(...)`, `setRandom(...)` ou `reset()` — adicionados apenas porque um teste precisou deles, não porque o design real os exija.

```ts
// payment-service.ts  (código de PRODUÇÃO)
export class PaymentService {
  #ledger: Entry[] = [];

  charge(amount: number) { /* ... */ }

  // Nada em produção jamais chama estes — apenas os testes chamam:
  getLedgerForTest() { return this.#ledger; }          // expõe detalhes internos
  setClockForTest(now: () => Date) { this.now = now; } // seam exclusivo para testes
  FTO_reset() { this.#ledger = []; }                   // "For Tests Only"
}

```

Uma verificação rápida: `grep -rn 'forTest\|ForTesting\|FTO_' src/` que retorne ocorrências no código-fonte de produção, ou uma varredura de código morto (por exemplo, Knip em modo de produção) que reporte um export como não utilizado enquanto um teste claramente o importa.

## Reasons for the Problem

**Por que acontece**

* _Adaptar testes a código não testável._ Quando o código legado não foi projetado para ser testável, a forma mais rápida de fazer asserções sobre um resultado é abrir um buraco no SUT e ler suas entranhas — Meszaros aponta isso como a principal causa do _For Tests Only_.
* _APIs assimétricas._ Os clientes reais usam um objeto de uma forma (escrita); os testes o usam de forma simétrica (escrever **e então** ler de volta para verificar), de modo que os testadores "precisam" de acessadores que nenhum chamador de produção precisa.
* _Pressão de prazo._ Adicionar uma porta dos fundos é mais barato no momento do que refatorar para um design no qual o comportamento é observável por meio do contrato público.

**Por que é prejudicial**

* _Legibilidade._ A API pública deixa de dizer a verdade — os mantenedores não conseguem distinguir o contrato real do andaime de teste, e cada leitor tem que se perguntar "esse método é realmente usado?"
* _Encapsulamento e confiabilidade._ O estado interno se torna alcançável e mutável no código que vai para produção. Uma chamada perdida a `FTO_reset()` ou um setter vazado pode corromper o estado em produção; a superfície extra também incha o bundle e amplia a superfície de ataque.
* _Falsa confiança._ Testes que cutucam o estado privado fazem asserções sobre a _implementação_, não sobre o _comportamento_. Eles podem continuar verdes enquanto o contrato público está quebrado, e quebram em refatorações inofensivas — testes frágeis que testam a coisa errada.
* _Manutenibilidade._ Os membros exclusivos para testes parecem código morto, mas não podem ser excluídos; cada mudança precisa levar em conta chamadores fantasmas, e o smell tende a se multiplicar à medida que mais testes reutilizam a porta dos fundos.

## Treatment

Trate a porta dos fundos como um sinal de design, não como um detalhe de fixture.

1. **Teste primeiro por meio do comportamento observável.** Faça asserções sobre valores de retorno, eventos emitidos, saída persistida ou interações com colaboradores (via test doubles) em vez de alcançar os detalhes internos. A maioria dos acessadores `getXForTest` desaparece assim que você verifica o que o objeto _faz_, e não o que ele _guarda_.
2. **Use uma Test-Specific Subclass** quando você genuinamente precisar de acesso interno. Estenda a classe no teste para expor um membro `protected`, em vez de ampliar a visibilidade em produção.
3. **Faça das seams parte do design real, não escotilhas exclusivas para testes.** Injetar um relógio ou um RNG por meio do construtor normal é injeção de dependência legítima; um mutador `setClockForTest()` é um smell. Se uma seam só faz sentido para os testes, empurre o comportamento para um **Strategy/Null Object** que a produção instala por padrão e que o teste troca.
4. **Se a exposição for realmente inevitável, rotule-a de forma evidente e isole-a.** Marque-a com `@VisibleForTesting` / `@internal` (ou uma convenção de nomenclatura `FTO_`) e garanta que o código de produção nunca a chame (veja os detectores). Uma seam marcada e protegida é melhor do que uma silenciosa.
5. **Cace os infratores existentes.** Faça `grep` por `forTest`/`ForTesting`/`FTO_` e rode uma ferramenta de uso/código morto, como o Knip em modo de produção, para revelar exports referenciados apenas por arquivos de teste.

```ts
// ANTES — a produção carrega um acessador exclusivo para testes
export class Cart {
  #items: Item[] = [];
  add(i: Item) { this.#items.push(i); }
  getItemsForTest() { return this.#items; } // apenas para testadores
}
// teste
expect(cart.getItemsForTest()).toHaveLength(1);

```

```ts
// DEPOIS — verifique o comportamento por meio do contrato real
export class Cart {
  #items: Item[] = [];
  add(i: Item) { this.#items.push(i); }
  get count() { return this.#items.length; }
  get total() { return this.#items.reduce((s, i) => s + i.price, 0); }
}
// teste
cart.add({ price: 10 });
expect(cart.count).toBe(1);
expect(cart.total).toBe(10);

```

Se você ainda precisar de acesso interno, restrinja a seam aos testes com uma subclasse, em vez de ao mundo inteiro:

```ts
// a produção permanece limpa: queue é protected, não public
export class Scheduler {
  protected queue: Job[] = [];
  enqueue(j: Job) { this.queue.push(j); }
}
// apenas no arquivo de teste
class TestScheduler extends Scheduler {
  peek() { return this.queue; }
}

```

## Detected by

- **sonar** `java:S5803` — Membros "@VisibleForTesting" não devem ser acessados a partir do código de produção (https://rules.sonarsource.com/java/RSPEC-5803/)
