How to write Test Data Builders in Apex?

I need to setup test data in proprietary cloud platform ( where I have no access to advanced testing frameworks. Besides that you can read my code example like it would be Java.

Setting up data basically means to insert records of a quite complex object structure into the database. I decided to go with the Test Data Builder pattern described in this blog post and the related book.

It took me a while to realize that this makes everything much harder as you have to decide where to put your actual DML (meaning when do you insert the record you build).

If you do it naively in the build() I see no way to optimize / bulkify DML statements – which would be very important at the platform.

On the other hand if you pass around Builder instances instead of Record instances around and build everything in the end you need extra methods to pass (in-memory but no yet persisted records) around.

public class OpportunityBuilder {

  private Account parentAccount
    public Opportunity record;
    private List<LineItemBuilder> lineItemBuilders;

  public OpportunityBuilder(Account acc) {
    record = new Opportunity();
    record.Name = ...
    record.Account = acc.Id; 
    lineItemBuilders = new List<LineItemBuilder>();

  public OpportunityBuilder add(LineItemBuilder lib) {
    lineItemBuilders.add( lib );
    return this;

  public Opportunity build() {
    insert record;

    List<LineItem> lis = new List<LineItem>();
    for(LineItemBuilder builder : lineItemBuilders) {
        LineItem li = builder.record;
        li.Opportunity = record.Id;  // Id requires previous DML
    insert lis;

    return record;

My question now is:

  1. How can I make my Builder classes super-extensible? Delay DML and pass Builders instead of records?
  2. Do you know of any resource which enhances the above pattern for database use?
  3. What other solutions do you know that would be an alternative?


UPDATE: A much improved and real-life tested version can be found in this GitHub repo:

Thanks to Andrew Fawcett and his amazingly powerful UnitOfWork implementation I was able to create a base class to create amazingly simple Builder classes per Domain object.

Those not only have the general benefits of TestDataBuilders over Helper classes but also:

  • Care about the DML as pure In-Memory tests are harder on
  • Take care of bulkification and Governor Limits
  • Could become an new Enterprise pattern always using the singular SObject names for custom objects

I’m planning on writing a blog post giving more code examples but I try to show the basics here.

Base class

public virtual class DomainObject {
    private static fflib_SObjectUnitOfWork uow = initUnitOfWork();
    public SObject record;
    public DomainObject(SObject standalone) {
    public DomainObject(SObject child, Schema.SObjectField parentRelationship, DomainObject parent) {
        register(parentRelationship, parent.record);
    public DomainObject(SObject linker, 
                        Schema.SObjectField leftRelationship, DomainObject left, 
                        Schema.SObjectField rightRelationship, DomainObject right) {
                            this(linker, leftRelationship, left);
                            register(rightRelationship, right.record);
    public DomainObject persist() {
        uow = initUnitOfWork();
        return this;
    protected DomainObject addChild(DomainObject child, Schema.SObjectField parentRelationship){
        uow.registerRelationship(child.record, parentRelationship, record);
        return this;
    private void register(SObject record) {
        this.record = record;
        if(record.Id == null) {
    private void register(Schema.SObjectField relationship, SObject relatedRecord) {
        if(relatedRecord.Id == null) {
            uow.registerRelationship(record, relationship, relatedRecord);
        else {
            record.put(relationship, relatedRecord.Id);
    private static fflib_SObjectUnitOfWork initUnitOfWork() {
        return new fflib_SObjectUnitOfWork(new List<Schema.SObjectType>{ 

Domain object with father and child records:

public class Father extends DomainObject {
    private Father__c fht;
    public Father(Parent par) {
        super(new Father__c(), Father__c.mdr_Parent__c, par);
        fht = (Father__c) record;   
        fht.txt_Field1__c = 'default';
    public Father() {
        this(new Grandfather());
    public Father add(Child chl) {
        return (Father) addChild(chl, Child__c.lkp_Father__c);
    public Father addChild() {
        return (Father) add(new Child());
    //...many other builder methods

Usage in an integration test:

private class MyApp_Test { 
    private static void worksAsDefined() {
        // Setup 
        Father bob = new Father()
                            .add(new Child()

        // Exercise 
        // Verify 

Source : Link , Question Author : Robert Sösemann , Answer Author : Robert Sösemann

Leave a Comment