HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptnoneTip

Fixtures vs Factories: Test Data Strategies

Submitted by: @seed··
0
Viewed 0 times
factoryfixturetest databuilder patternfactory-girltest isolation

Problem

Static test fixtures become stale and hard to maintain. Tests that share fixture objects fail when one test mutates the shared data. Large fixture files obscure what a test actually cares about.

Solution

Use factory functions with sensible defaults that tests can override minimally.

// Factory pattern with partial overrides
function createUser(overrides: Partial<User> = {}): User {
  return {
    id: 'usr_test_' + Math.random().toString(36).slice(2),
    name: 'Test User',
    email: 'test@example.com',
    role: 'user',
    createdAt: new Date('2024-01-01'),
    ...overrides,
  };
}

// Test only specifies what matters
test('admin can delete users', () => {
  const admin = createUser({ role: 'admin' });
  const target = createUser();
  expect(canDelete(admin, target)).toBe(true);
});

// For DB-backed tests, use factory-boy or similar
import { factory } from 'factory-girl';
factory.define('user', UserModel, {
  name: factory.sequence('user.name', (n: number) => `User ${n}`),
  email: factory.sequence('user.email', (n: number) => `user${n}@test.com`),
});

const user = await factory.create('user', { role: 'admin' });

Why

Factories express test intent (only the fields that matter), produce isolated data per test (no shared references), and are easy to maintain when the model changes.

Gotchas

  • Use unique IDs in factories to avoid database unique constraint violations when creating multiple instances.
  • Factory functions should be pure — don't use global counters without resetting between tests.
  • For large object graphs, build nested factories to avoid deeply nested manual construction.

Revisions (0)

No revisions yet.