SuperAPI AI Directory

dotnet-testing-test-data-builder-pattern

Testing & quality

View repository

Updated 10-15 23:45

About this skill

Test Data Builder Pattern

Core Concepts

What Is the Test Data Builder Pattern?

The Test Data Builder Pattern is an improved version of the Object Mother Pattern, primarily solving the following problems:

  1. Problem of fixed test data: Object Mother provides fixed test objects, making it difficult to adjust for specific test scenarios
  2. Unclear test intent: When creating objects directly, the focus of the test is easily obscured by a large number of property settings
  3. Duplicate code: Similar object creation logic appears repeatedly across multiple tests

Why Is the Builder Pattern Needed?

// ❌ 問題:過多參數設定,測試意圖不明確
var user = new User
{
    Name = "John Doe", Email = "john@example.com", Age = 30,
    Roles = new[] { "User" }, Settings = new UserSettings { Theme = "Dark", Language = "zh-TW" },
    IsActive = true, CreatedAt = DateTime.Now, ModifiedAt = DateTime.Now
};

// ✅ 改善:意圖明確,只設定測試關注的屬性
var user = UserBuilder.AUser().WithName("John Doe").WithValidEmail().Build();

Implementation Guide

Basic Builder Structure

A standard Test Data Builder should include:

  1. Default values: Provide reasonable default values for all required properties
  2. Fluent interface: Use With* method chaining to set properties
  3. Semantic methods: Provide meaningful default creators (such as AnAdminUser()、ARegularUser())
  4. Build method: Finally creates and returns the target object

Covers a complete UserBuilder implementation (default values, With* fluent methods, semantic static factory methods, Build method), a single test scenario, and an example used with Theory.

For a complete Builder implementation and test usage examples, refer to references/builder-implementation.md


Best Practices

Covers five practices: provide reasonable default values, use semantic naming (UserScenarios), composition between Builders (OrderBuilder composing UserBuilder + ProductBuilder), avoid overcomplication, and centrally manage test data (TestData static class).

For complete best practices and advanced patterns, refer to references/best-practices-and-patterns.md


Comparison with Other Patterns

Test Data Builder vs. Object Mother

Feature Test Data Builder Object Mother
Flexibility Highly flexible, can be adjusted for tests Fixed test data
Readability Fluent interface, clear intent Need to inspect method implementation
Maintainability Centrally managed, easy to modify Changes affect all tests
Use cases Unit tests, scenario tests Simple integration tests

Test Data Builder vs. AutoFixture

Feature Test Data Builder AutoFixture
Degree of control Complete control over object creation Automatically generated, less control
Setup complexity Builder must be created manually Almost zero setup
Test intent Very clear Requires additional explanation
When applicable Tests requiring precise control Mass data generation, anonymous testing

Recommendation: Test Data Builder and AutoFixture can complement each other. Use AutoFixture for simple scenarios, and use the Builder Pattern for complex scenarios or when clear intent is required.

Practical Examples

Please refer to templates/ for complete implementation examples in the directory:

  • user-builder-example.cs - Basic User Builder implementation
  • advanced-builder-scenarios.cs - Advanced Builder composition and usage scenarios
  • builder-with-theory.cs - Practical examples of Builder with xUnit Theory

Output Format

  • Generate Builder class files (e.g., UserBuilder.cs、ProductBuilder.cs), placed in the test project's Builders/ directory
  • Each Builder includes default values,With* fluent methods, semantic static factory methods, and Build() methods
  • If shared across tests is needed, generate TestData.cs static classes to centrally manage common test data
  • Generate corresponding test class files (*Tests.cs), demonstrating how to use the Builder

References

Original Articles

This skill content is distilled from the "Old-School Software Engineer's Testing Practice - 30-Day Challenge" series:

Further Reading

Related Skills

  • autofixture-basics - Using AutoFixture to automatically generate test data
  • xunit-project-setup - Basic setup for xUnit test projects
  • test-naming-conventions - Test naming conventions

Summary

The Test Data Builder Pattern is an important technique for writing maintainable tests:

  • When to Use: test objects have multiple properties, test data needs to be reused, and clear intent should be expressed
  • Core Advantages: improves readability, reduces maintenance costs, and enhances expressiveness
  • Considerations: keep the Builder simple, provide reasonable default values, and use semantic method names