Test Data Factory in Salesforce

In this post we will talk about how to create Test Data Factory in Salesforce with some Test class best practices. Common test utility classes are public test classes that contain reusable code for test data creation.

Test Data Factory Example

The TestDataFactory/ testutility  class is a special type of class — It is a public class that is annotated with @isTest and and as such, are excluded from the organization code size limit and execute in test context and can be accessed only from a running test. Let see the use case of Test data factory in Salesforce.

Use case : What about if we need to create multiple test classes in Salesforce and in most of the test classes we need to create some common test data like Account,Contact and Opportunity etc ? 

In this use case we can create one Util test class to create the test data. In that case, we can use the same test data in all test classes.

Test Data Factory pattern

Test utility classes/TestDataFactory contain methods that can be called by test methods to perform useful tasks, such as setting up test data. Here is example of Test Data Factory pattern.

Step 1:- Create TestDataFactory class

@isTest
public class TestDataFactory {
	public static Account createAccount(Boolean doInsert) {
		createAccount('testAccount', doInsert);
	}
	
	public static Account createAccount(String name, Boolean doInsert) {
		Account acc = new Account(name = name);
		if(doInsert) {
			insert acc;
		}
		return acc;
	}
	
	public static Contact createContact(Boolean doInsert) {
		Account acc = createAccount(true);
		return createContact(acc.id, true);
	}
	
	public static Contact createContact(Id accountId, Boolean doInsert) {
		Contact c = new Contact(firstName = 'Apex', lastName = 'Hours', accountId = accountId);
		if(doInsert) {
			insert c;
		}
		return c;
	}
	public static List<Opportunity> createOpportunity(Id accountId, Integer numOpps) {
		List<Opportunity> opps = new List<Opportunity>();
		for(Integer i = 1; i <= numOpps; i++) {
			Opportunity opp = new Opportunity();
			opp.name = 'Account ' + i;
			opp.accountId = accountid;
			opp.amount = 1000;
			opp.closeDate = Date.today().addDays(5);
			opp.stageName = 'Prospecting';
			opps.add(opp);
		}
		return opps;
	}
}

You can overload the method base on your requirement. In above example we create two different method to create contact record. One if you want to create contact record with account , In that case we can call createContact method like below

@isTest 
public void myUnitTest() {
    Account acc = TestDataFactory.createAccount(true);
    Contact cont = TestDataFactory.createContact(acc.id, true); 
}

if you want to create account and contact together call createContact method with one param like below

@isTest
public void myUnitTest() {
    Contact cont = TestDataFactory.createContact(true);    
	// This method will create account and contact
}

Summary

Like that you can create your test data in test data factory in Salesforce.

Amit Chaudhary
Amit Chaudhary

Amit Chaudhary is Salesforce Application & System Architect and working on Salesforce Platform since 2010. He is Salesforce MVP since 2017 and have 17 Salesforce Certificates.

He is a active blogger and founder of Apex Hours.

Articles: 469

2 Comments

  1. I can see this as being more useful then the @TestSetUp approach and keeps your test classes cleaner. I do wonder though at some point whether this could get unwieldy as you add more and more methods for additional other classes.

    I guess technically you could create a set under different namespaces to have a set of TestDataFactory classes, such as namespacing using maybe different business process/scenarios like :

    AccountManagement
    CaseManagement
    ProductManagement

    Or possibly create abstract class with common create, update and delete methods, passing a given SObject and then based on that call other sub classes that do the heavy lifting.

    Spitballing I know, but just thinking ahead 🙂

    Thanks,
    Paul

  2. Hi Amit,

    In the first method where you are creating Account, there need to be a return statement. I know this is an obvious typo but still if you missed it you can update the blog accordingly.

    And thank you for your priceless content, your blogs are always insightful.

Leave a Reply

Your email address will not be published. Required fields are marked *