Test Data Builders
Construct valid test objects with sensible defaults and only the fields that matter.
- unit
- fixtures
- readability
Problem
Tests build objects inline with every field spelled out. The one field that matters to the test is lost in noise, and adding a required field breaks dozens of tests at once.
Solution
Use a builder (or factory) that returns a valid object from sensible defaults and lets each test override only the fields it cares about. Intent jumps out, and a new required field needs one change — in the builder.
Keep builders pure and deterministic; if you need uniqueness, inject a seed rather than reaching for random values.
Snippet
function aUser(overrides: Partial<User> = {}): User {
return {
id: 'u-1',
name: 'Test User',
email: 'user@example.com',
role: 'member',
...overrides,
};
}
// The test states only what matters.
it('blocks members from the admin panel', () => {
expect(canAccessAdmin(aUser({ role: 'member' }))).toBe(false);
});Pitfalls
- Random data by default — it makes failures non-reproducible. Prefer fixed defaults, inject a seed when needed.
- Builders that can produce invalid objects; keep defaults valid so tests start from a known-good state.
- Over-engineering with deep fluent chains when a function with a Partial override is enough.