function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
chriscwharrischriscwharris 

Apex Test Data Factory master detail relationships

I have an apex trigger that runs on an object that is 3 levels down in a master detail hierarchy. I'm starting to write a test class for the trigger but need to set up the test data for the test methods. Due to the complexity of requiring a parent and grandparent in place before creating the actual records being tested I figured I would use a utility class.

Having investigated various onine resources I can see lots of examples of using a utility class to create a single type of object record and have that returned as an array which can be processed in the test class but I'm not sure how you deal with multiple levels of relationship and different object types if you need to access both the parent and grandparent records from the test methods as they are both required.

As an example:

Firstly create in Utility Class
Grandparent Record (Custom Object A)
  ->    Parent Record (Custom Object B)

Then the following is created in the test Class methods but needs to access both objects created above
     ->   Detail Record test 1 (Custom Object C) (Child of Object B which is child of Object A)
     ->   Detail Record test 2 (Custom Object C) (Child of Object B which is child of Object A)
     ->   Detail Record test 3 (Custom Object C) (Child of Object B which is child of Object A)

I may be over thinking this, any advice, examples or tips appreciated!

 
SFDC Dev 2269SFDC Dev 2269
Well, according to what I understood from your question you wanted to create test data which is three levels, So, here is the Example you can just refer it:
// Create Utility Class
@isTest
public class TestDataFactory {

    // Create GrandParent__c records
    public static List<GrandParent__c> createGrandParents(Integer count) {
        List<GrandParent__c> grandParentLst = new List<GrandParent__c>();
        for (Integer i = 0; i < count; i++) {
            GrandParent__c obj = new GrandParent__c();
            obj.Name = 'Test Grand Parent Rec';
            // Add fields to be populated
            grandParentLst.add(obj);
        }
        insert grandParentLst;
        return grandParentLst;
    }
    
    // Create Parent__c records using inserted grandParents 
    public static List<Parent__c> createParents(List<GrandParent__c> grandParents) {
        List<Parent__c> parents = new List<Parent__c>();
        for (Integer i = 0; i < grandParents.size() - 1; i++) {
            parents.add(
                new parent__c(
                    Name = 'Test Parent'
                    GrandParentId = grandParents[i].Id;
                )
            );
        }
        
        insert parents;
        return parents;
    }
    
    // Create Child__c records using inserted parents 
    public static List<Child__c> createChildren(List<Parent__c> parents) {
        List<Child__c> children = new List<Child__c>();
        for (Integer i = 0; i < parents.size() - 1; i++) {
            children.add(
                new Child__c(
                    Name = 'Test Child'
                    ParentId = parents[i].Id;
                )
            );
        }
        
        insert children;
        return children;
    }
}



here's how you call this in your test class:
 
List<Child__c> childLst =
    TestDataFactory.createChildren(
        TestDataFactory.createParents(
            TestDataFactory.createGrandParents(10)
        )
    );


    
Or 
 
List<GrandParent__c> grandParents = TestDataFactory.createGrandParents(10);
List<Parent__c> parents = TestDataFactory.createParents(grandParents);
List<Child__c> childLst = TestDataFactory.createChildren(parents);

 
chriscwharrischriscwharris
That's a great start, thanks! I'll take a look...