← Concepts

阅读中文版本

Test Data Builders

Test data builders construct valid objects with sensible defaults plus per-test overrides, keeping fixtures readable and centralizing invariants as the domain evolves.

testing

Definition

A builder provides a fluent or parameterized factory for domain objects: required fields and invariant-satisfying defaults live inside the builder; each test overrides only what its scenario varies. Refactors to the domain touch the builder, not hundreds of inline fixture literals. It replaces object literals duplicated across tests with one source of validity.

Context and scope

Applied wherever tests construct entities — users, orders, invoices — especially with complex validation. Complements fixtures and factories in ORMs.

Common misconceptions

  • Builders are overengineering for simple structs — inline literals duplicated across fifty tests are the maintenance problem builders exist to remove
  • The builder should expose every field — expose what tests actually vary; hidden defaults keep noise down and intent readable
  • One builder per entity is enough — variant methods (anOverdueInvoice, aSuspendedUser) encode meaningful scenarios better than flags

Anti-patterns

  • Copying a 30-field literal between tests and editing one field, letting invariant violations slip into the copies
  • Building objects with impossible states because the builder bypasses domain validation
  • Naming builder overrides after field names only, losing the scenario intent the test reader needs

Related concepts

Related examples

Authoritative source

https://martinfowler.com/bliki/TestDataBuilder.html

What it is

Test fixtures rot through duplication: each test hand-assembles domain objects, and the next domain change edits them all. Builders invert it — construction knowledge centralized, variation localized.

How it works

The builder holds valid defaults and constructs through the domain factory or entity itself so illegal states cannot exist. Tests chain overrides for the fields under test. Scenario helpers — named for business meaning — wrap common configurations, making the test read as intent rather than field soup.

When to reach for it

Any entity constructed in more than a handful of tests, any object with interdependent fields, and any domain where validity itself evolves. For pure value structs, plain literals remain fine.

Pitfalls

Builders that bypass constructors or validation reintroduce impossible states. God-builders with every field exposed produce tests indistinguishable from serialized data. Defaults drift from business reality silently — review them like production code, because they encode domain assumptions.