---
title: "Inicialização no Construtor"
type: "test-smell"
slug: "constructor-initialization"
url: "http://localhost:3000/pt-br/test-smells/constructor-initialization.md"
category: "Maus Cheiros de Fixture"
description: "Uma classe de teste inicializa seus campos de fixture em um construtor em vez de no hook de setup dedicado do framework (setUp / @BeforeEach / TestInitialize), contornando o ciclo de vida do teste."
---
# Inicialização no Construtor

> Uma classe de teste inicializa seus campos de fixture em um construtor em vez de no hook de setup dedicado do framework (setUp / @BeforeEach / TestInitialize), contornando o ciclo de vida do teste.

## Signs and Symptoms

Uma classe de teste tem um construtor explícito que constrói o sistema sob teste, os mocks ou os campos compartilhados — trabalho que pertence ao hook de setup do framework (`setUp()` / `@Before` / `@BeforeEach` no JUnit, `[TestInitialize]` no MSTest, `beforeEach` no Jest/Vitest).

Sinais reveladores:

* A classe de teste declara um construtor que atribui a campos `final`/de instância.
* A configuração da fixture vive fora do ciclo de vida que o framework realmente gerencia — de modo que `@BeforeEach`/`@AfterEach`, o setup da classe base e a reinicialização por teste são silenciosamente contornados ou executados em uma ordem confusa em relação ao construtor.
* O setup assíncrono é impossível: você não pode usar `await` dentro de um construtor, então o trabalho assíncrono de fixture acaba forçado para o lugar errado ou duplicado.

Forma canônica em JUnit (do catálogo de test smells):

```java
public class TagEncodingTest extends BrambleTestCase {
    private final CryptoComponent crypto;
    private final SecretKey tagKey;

    public TagEncodingTest() {                 // smell: inicialização no construtor
        crypto = new CryptoComponentImpl(new TestSecureRandomProvider());
        tagKey = TestUtils.getSecretKey();
    }
}

```

Análogo em JS/TS — fixture construída uma única vez no escopo de `describe`/módulo (o equivalente ao construtor) em vez de por teste:

```ts
describe('Cart', () => {
  const cart = new Cart();          // construído uma vez, vaza estado entre os testes
  it('adds an item', () => { cart.add(apple); expect(cart.size).toBe(1); });
  it('starts empty', () => { expect(cart.size).toBe(0); }); // falha: enxerga apple
});

```

## Reasons for the Problem

**Por que acontece**

* Desenvolvedores não familiarizados com o propósito do hook de setup recorrem ao recurso da linguagem que já conhecem — o construtor — para inicializar os campos.
* Parece mais limpo: campos `final` mais um construtor soam idiomáticos, e uma IDE pode até gerar o construtor para você.
* Cargo cult a partir de classes de produção, onde a inicialização no construtor _é_ o padrão correto.

**Por que é prejudicial**

* **Contorna o ciclo de vida do teste.** Os frameworks prometem estado novo a cada teste por meio do hook de setup e de um par `@BeforeEach`/`@AfterEach` (ou `beforeEach`/`afterEach`). A lógica escondida em um construtor fica fora desse contrato, de modo que a limpeza, o setup da classe base e as garantias de ordenação podem não se aplicar como esperado.
* **Vazamento de estado e instabilidade.** Em frameworks que reutilizam uma única instância (ou quando você guarda a fixture em uma variável compartilhada/com escopo de `describe`), as mutações de um teste vazam para o seguinte. Os testes passam ou falham dependendo da ordem de execução — falsa confiança e falhas intermitentes.
* **Sem setup assíncrono.** Um construtor não pode usar `await`. Qualquer setup que precise de I/O, de uma conexão de banco de dados ou de um servidor iniciado não consegue viver ali de forma limpa; as pessoas contornam isso com chamadas bloqueantes ou com código duplicado por teste.
* **Legibilidade/consistência.** Revisores e ferramentas esperam as fixtures no hook convencional. Dividir a inicialização entre um construtor e um método de setup torna a fixture real difícil de encontrar e fácil de errar.

**Ressalva — depende do framework.** Esta não é uma regra universal. No **xUnit.net**, o construtor _é_ o setup idiomático por teste (combinado com `IDisposable` para o teardown), e o MSTest até traz uma regra oposta, opcional (`MSTEST0020`), que prefere construtores em vez de `[TestInitialize]`. Trate a "Inicialização no Construtor" como um smell especificamente onde o seu framework fornece um hook de setup dedicado (JUnit, MSTest clássico, NUnit) e você está contornando-o.

## Treatment

Mova a inicialização dos campos para fora do construtor e para dentro do hook de setup do framework, e prefira um estado novo por teste em vez de instâncias compartilhadas.

1. Exclua o construtor da classe de teste; declare os campos e atribua-os no hook de setup (`@BeforeEach`/`setUp()` para JUnit, `[TestInitialize]` para MSTest, `beforeEach` para Jest/Vitest).
2. Se o setup for assíncrono, isso é obrigatório — o hook pode usar `await`; um construtor não pode.
3. No JS/TS, construa a fixture _dentro_ de `beforeEach` (reatribuindo um `let`) em vez de uma única vez no escopo de `describe`/módulo, para que cada teste receba um objeto limpo.
4. Mantenha o teardown simétrico: combine `@BeforeEach` com `@AfterEach` (ou, no estilo de construtor do xUnit.net, implemente `IDisposable`).

Antes → depois (JUnit):

```java
// antes
public class TagEncodingTest {
    private final CryptoComponent crypto = new CryptoComponentImpl(...);
}

// depois
public class TagEncodingTest {
    private CryptoComponent crypto;

    @BeforeEach
    void setUp() {
        crypto = new CryptoComponentImpl(...);
    }
}

```

Antes → depois (Jest/Vitest):

```ts
describe('Cart', () => {
  let cart: Cart;
  beforeEach(() => { cart = new Cart(); }); // novo a cada teste
  it('adds an item', () => { cart.add(apple); expect(cart.size).toBe(1); });
  it('starts empty', () => { expect(cart.size).toBe(0); });
});

```

Se a fixture for genuinamente imutável e custosa (e o seu framework suportar isso), um hook de uma única vez, como `@BeforeAll`/`beforeAll`, é aceitável — mas apenas para estado compartilhado verdadeiramente somente leitura, nunca para objetos que os testes mutam.

## Detected by

- **tsDetect (Test Smell Detector)** `Constructor Initialization` (https://testsmells.org/pages/testsmells.html)
- **MSTest Roslyn analyzers** `MSTEST0019` (https://learn.microsoft.com/en-us/dotnet/core/testing/mstest-analyzers/mstest0019)
