---
title: "General Fixture"
type: "test-smell"
slug: "general-fixture"
url: "http://localhost:3000/en/test-smells/general-fixture.md"
category: "Fixture Smells"
description: "A shared setup builds one big \"kitchen-sink\" fixture covering every test's needs, but each individual test exercises only a small slice of it."
---
# General Fixture

> A shared setup builds one big "kitchen-sink" fixture covering every test's needs, but each individual test exercises only a small slice of it.

## Signs and Symptoms

A single `beforeEach`/`setUp` (or shared module-level setup) constructs lots of objects, seeds many records, and wires up several mocks — and any given test touches only one or two of them. The detection heuristic from the test-smell catalog is simply: _not all fields created in setup are used by all test methods_.

How to recognize it:

* The setup block is long and grows every time a new test is added.
* To understand a single test you must scroll up and reverse-engineer which parts of the fixture actually matter to it.
* Many tests fail or need editing when you change one shared object that most of them don't even care about.
* The same fixture serves wildly different scenarios (creation, validation, payment, permissions) from one place.

```js
// Smell: one fixture for everything; each test uses a sliver of it
let user, admin, product, cart, order, paymentGateway, shippingZone;

beforeEach(() => {
  user            = createUser({ name: 'Ada' });
  admin           = createAdmin();
  product         = createProduct({ price: 10 });
  cart            = createCart(user, [product]);
  order           = createOrder(cart);
  paymentGateway  = mockGateway();
  shippingZone    = createZone('EU');
});

test('cart subtotal sums its line items', () => {
  // only needs cart + product, yet pays for admin, order, gateway, zone…
  expect(cart.subtotal()).toBe(10);
});

```

## Reasons for the Problem

**Why it happens**

* **DRY applied too aggressively.** Setup is consolidated into one shared hook to "avoid duplication," so every new test's needs get bolted onto the same fixture.
* **Organic growth.** The fixture accretes objects as tests are added, and nobody prunes what older tests no longer use.
* **Implicit setup inertia.** Once a big `beforeEach` exists, adding one more line is easier than creating a focused fixture for the new case.

**Why it hurts**

* **Readability / Tests-as-Documentation.** A test should read as a clear cause→effect. When most of the fixture is irrelevant noise, the reader can't tell what actually drives the result. Meszaros' antidote, the _Minimal Fixture_, exists precisely because a test using the smallest fixture is always easier to understand.
* **Maintainability.** A change demanded by one test (e.g. give `product` a new required field) forces edits to setup shared by all tests, creating ripple-effect breakage and coupling unrelated tests together.
* **Reliability.** Shared, mutable fixture state lets tests influence each other and makes failures hard to localize — a classic source of order-dependent flakiness.
* **Speed.** Every test pays the full cost of building the whole fixture. General Fixture is listed among the causes of Slow Tests.
* **False confidence.** Tests become over-specified against incidental fixture details, so they pass or fail for reasons unrelated to the behavior under test.

## Treatment

Aim for a **Minimal Fixture**: each test sets up only what that test needs, and nothing more.

1. **Inventory usage.** For each shared field, list which tests actually read it. Anything used by only a subset is a candidate to move out of the shared setup.
2. **Push construction into Creation Methods / test-data builders (Delegated Setup).** Keep tests concise without forcing one giant fixture — each test calls a builder and overrides only the attributes relevant to it.
3. **Prefer a Fresh Fixture per test** over a long-lived shared one, eliminating cross-test coupling and mutable shared state.
4. **Split by scenario.** If groups of tests genuinely share a _small_ fixture, separate them into focused `describe` blocks (or test classes), each with its own minimal setup.
5. **Keep in `beforeEach` only what is truly common and small;** move the rest inline so cause and effect sit next to the assertion.

```js
// Before: general fixture in a shared hook (see Signs & Symptoms)

// After: minimal, delegated setup — each test builds only what it needs
test('cart subtotal sums its line items', () => {
  const cart = aCart().withItem(aProduct().price(10)).build();
  expect(cart.subtotal()).toBe(10);
});

test('checkout charges the payment gateway', () => {
  const gateway = mockGateway();
  const cart    = aCart().withItem(aProduct().price(10)).build();

  checkout(cart, gateway);

  expect(gateway.charge).toHaveBeenCalledWith(10);
});

```

Each test now reads top-to-bottom as a self-contained story, builders absorb the boilerplate, and changing one scenario no longer disturbs the others.
