What Are Fixtures and Factories?
A test fixture is a piece of known, reusable test data — an object, file, or state — that multiple tests rely on as a starting point. A factory is a function that generates such fixture objects programmatically, typically with sensible default values that any individual test can override.
Cricket analogy: A test fixture is like a standard practice pitch prepared to fixed specifications so every batting drill for the U-19 squad starts from the same known surface, rather than each player testing on a different random ground.
Building Factory Functions with Overrides
A well-designed factory function returns an object with realistic defaults for every field, and accepts an overrides parameter spread onto that default object so a specific test can customize only the fields it cares about while every other field stays predictable.
Cricket analogy: A createPlayer({ overrides }) factory that lets you override the strike rate is like a coach's drill generator that produces a standard net session but lets you tweak just the bowling speed to simulate facing Mitchell Starc specifically.
// fixtures/userFactory.js
let idCounter = 1;
export function createUser(overrides = {}) {
return {
id: idCounter++,
name: 'Test User',
email: `user${idCounter}@example.com`,
role: 'member',
createdAt: new Date('2026-01-01').toISOString(),
...overrides,
};
}
// user.test.js
import { createUser } from './fixtures/userFactory';
test('admin users can delete posts', () => {
const admin = createUser({ role: 'admin' });
expect(canDeletePost(admin)).toBe(true);
});
test('member users cannot delete posts', () => {
const member = createUser({ role: 'member' });
expect(canDeletePost(member)).toBe(false);
});Static Fixtures vs. Randomized Data
Static fixture files, like a saved sample-response.json, are ideal when a test needs exact, unchanging reference data. Libraries such as faker.js instead generate realistic but randomized data on each call, which is useful for exercising a wider range of inputs without hand-writing every variation.
Cricket analogy: A static fixture file like sample-scorecard.json is like a museum's archived scorecard from a famous match kept exactly as-is, referenced repeatedly for historical analysis without ever changing.
Factory functions are typically kept in a dedicated fixtures/ or test-utils/ directory and exported so they can be imported across many test files, keeping test data creation DRY and consistent with your actual data shapes.
Hardcoding a fixed id or email in every fixture object can cause unique-constraint violations or false test passes when multiple factory-created objects collide; incrementing counters or using faker's randomization avoids this.
- A test fixture is a known, reusable piece of test data or state.
- A factory function generates fixture objects programmatically, often with sensible defaults.
- Factories accept an overrides object so individual tests can customize only what they need.
- Static fixture files (JSON, sample data) are good for exact, unchanging reference data.
- Libraries like faker.js generate realistic randomized data for broader test coverage.
- Keeping factories in a shared fixtures/ directory avoids duplicated, inconsistent test data across files.
- Unique fields (ids, emails) should be generated dynamically to avoid collisions between factory-created objects.
Practice what you learned
1. What is the primary benefit of a factory function over hardcoded fixture objects?
2. Why is faker.js often used alongside factory functions?
3. What problem can arise from hardcoding the same id in every object a factory creates?
4. When is a static JSON fixture file preferable to a factory function?
5. What does an overrides parameter in a factory function like createUser(overrides) typically do?
Was this page helpful?
You May Also Like
beforeEach() and afterEach()
Learn how Jest's beforeEach() and afterEach() hooks establish and tear down consistent test state so every test runs in isolation.
Testing React Components with React Testing Library
Learn how to test React components the way a user experiences them, using render, screen queries, userEvent, and async assertions.
Code Coverage with Jest
Understand how Jest measures code coverage across statements, branches, functions, and lines, and how to enforce thresholds in CI.