10 Best Practices for Writing Apex Test Classes in Salesforce – Examples Included

Apex Test classes are an essential part of Salesforce development, as they help ensure that your code is functioning correctly and that your business logic is sound. In this blog post, we will go over best practices for Apex Test classes, including tips for writing efficient and effective tests, as well as examples of how to implement these best practices in your own code.

① Use System.assert() statements

The System.assert() method is used to check if a particular condition is true or false in your Apex code. This is an essential tool for testing, as it allows you to check that your code is functioning as expected. For example, you can use System.assert() to check that a variable is not null, or that a method is returning the correct value.

Example:

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
Account a = new Account(Name='Test Account');
insert a;
System.assertEquals('Test Account', a.Name);
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

② Use Test.startTest() and Test.stopTest()

The Test.startTest() and Test.stopTest() methods are used to define a block of code that should be run in a separate test context. This is useful for testing code that makes use of governor limits, such as the number of records that can be queried in a single transaction. By using these methods, you can ensure that your tests will not exceed these limits, and that your code will function correctly in a production environment.

Example:

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
Test.startTest();
// code that uses governor limits
Test.stopTest();
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

③ Use Test Data Factory Methods

Creating test data is an important part of testing. It is important to create test data that is representative of the data that will be used in a production environment. A best practice is to use Test Data Factory methods to create test data. These methods should be separate from the test methods and should be used to create test data that can be used by multiple test methods.

Example:

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
Account a = createAccount();
System.assertEquals('Test Account', a.Name);
}
static Account createAccount() {
Account a = new Account(Name='Test Account');
insert a;
return a;
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

④ Use @testSetup

The @testSetup annotation is used to define a method that will be run before all test methods in the class. This is useful for setting up test data that is needed by multiple test methods. By using the @testSetup annotation, you can ensure that your test data is created only once, which can improve the performance of your tests.

Example:

@isTest
public class MyTestClass {
@testSetup static void setup() {
Account a = new Account(Name='Test Account');
insert a;
}
static testMethod void testMyMethod() {
Account a = [SELECT Name FROM Account WHERE Name='Test Account'];
System.assertEquals('Test Account', a.Name);
}
}
view raw MyTestClass hosted with ❤ by GitHub

⑤ Use @isTest(SeeAllData=false)

The @isTest annotation is used to define a class or method as a test class or method. The SeeAllData parameter can be used to specify whether or not the test class or method can access all data in the organization, or just data that is created by the test itself. By setting SeeAllData to false, you can ensure that your tests are not affected by data that is not related to the test, and that your tests will be more reliable.

Example:

@isTest(SeeAllData=false)
public class MyTestClass {
static testMethod void testMyMethod() {
Account a = new Account(Name='Test Account');
insert a;
System.assertEquals('Test Account', a.Name);
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

⑥ Use the @testVisible annotation

The @testVisible annotation is used to make an Apex class or method visible to test classes, even if it is defined as private. This is useful for testing methods or classes that are not accessible to test classes by default. By using the @testVisible annotation, you can ensure that your tests have access to the necessary methods and classes for testing.

Example:

public class MyClass {
@testVisible private static Integer myMethod() {
return 5;
}
}
@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
Integer result = MyClass.myMethod();
System.assertEquals(5, result);
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

⑦ Use the Test.setFixedSearchResults() method

The Test.setFixedSearchResults() method is used to set the search results that will be returned by a search query in a test class. This is useful for testing code that makes use of search queries, as it allows you to control the data that is returned by the query. By using the Test.setFixedSearchResults() method, you can ensure that your tests are not affected by changes in the data that is returned by the query.

Example:

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
List<Account> accounts = new List<Account>{
new Account(Name='Test Account 1'),
new Account(Name='Test Account 2')
};
insert accounts;
Test.setFixedSearchResults(accounts);
List<Account> results = [FIND 'Test Account*' IN ALL FIELDS RETURNING Account(Name)];
System.assertEquals(2, results.size());
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

⑧ Use the Test.loadData() method

The Test.loadData() method is used to load test data from a CSV file into your test class. This is useful for creating large amounts of test data, as it allows you to easily import data from a spreadsheet or other external source. By using the Test.loadData() method, you can ensure that your tests are not affected by changes in the data that is used by the test, and that your tests will be more reliable.

Example:

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
List<sObject> records = Test.loadData(Account.sObjectType, 'test_accounts');
System.assertEquals(10, records.size());
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

⑨ Use the Test.createStub() method

The Test.createStub() method is used to create a test stub for an Apex class or interface. This is useful for testing code that makes use of classes or interfaces that are not accessible in a test context, such as web service callouts or external Apex classes. By using the Test.createStub() method, you can ensure that your tests are not affected by changes in the behavior of the class or interface, and that your tests will be more reliable.

Example:

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
MyClass.MyWebService ws = Test.createStub(MyClass.MyWebService.class);
Test.setMock(WebServiceMock.class, ws);
// test code that makes use of the MyWebService class
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

①⓪ Avoid hard-coding test data

It’s important to avoid hard-coding test data in your test methods, as this can make it difficult to change the test data and can make it difficult to change the test methods if the test data changes. Instead, it’s best to use variables or methods to create test data, so that it can be easily changed or updated.

@isTest
public class MyTestClass {
static testMethod void testMyMethod() {
// BAD PRACTICE: Hard-coding test data
Account a = new Account(Name='Test Account', Industry='Technology');
insert a;
System.assertEquals('Test Account', a.Name);
System.assertEquals('Technology', a.Industry);
// GOOD PRACTICE: Using variables for test data
String accountName = 'Test Account 2';
String industry = 'Finance';
Account b = new Account(Name=accountName, Industry=industry);
insert b;
System.assertEquals(accountName, b.Name);
System.assertEquals(industry, b.Industry);
}
}
view raw MyTestClass.cls hosted with ❤ by GitHub

In the above example, the first test method uses hard-coded test data for the account name and industry. If the test data needs to be changed, the test method would have to be modified as well. In contrast, the second test method uses variables for the account name and industry. This makes it easy to change the test data without having to modify the test method.

Bonus

Use test methods that cover a variety of scenarios

It’s important to create test methods that cover a variety of scenarios, such as testing for different types of inputs, different edge cases, and different combinations of inputs. This will ensure that your code is thoroughly tested and will help you identify any potential issues that might not be caught by testing for a single scenario.

Use the @isTest(SeeAllData=true) parameter with caution

The SeeAllData parameter in the @isTest annotation is used to specify whether or not the test method can access all data in the organization, or just data that is created by the test itself. By setting SeeAllData to true, you can access all data in the organization, but this can also make the test more brittle and less reliable. Use this parameter with caution and only when it’s necessary for the test to access all data in the organization.

In summary, Apex Test classes are an important aspect of Salesforce development and following best practices can help ensure that your code is functioning correctly and that your business logic is sound. These best practices include using System.assert() statements, Test.startTest() and Test.stopTest() methods, Test Data Factory Methods, the @testSetup annotation, setting the @isTest(SeeAllData=false) parameter, Use the @testVisible annotation, Test.setFixedSearchResults() method, SeeAllData parameter, Test.loadData() method, Test.createStub() method, and running the tests regularly. Additionally, avoiding hard-coding test data, using test methods that cover a variety of scenarios can improve the quality of the test. By implementing these best practices in your own code, you can ensure that your code is functioning as expected, identify any potential issues early on, and ultimately save time and resources.

About the blog

SFDCLessons is a blog where you can find various Salesforce tutorials and tips that we have written to help beginners and experienced developers alike. we also share my experience and knowledge on Salesforce best practices, troubleshooting, and optimization. Don’t forget to follow us on:

Newsletter

Subscribe to our email newsletter to be notified when a new post is published.

Arun Kumar

Arun Kumar is a Certified Salesforce developer and Salesforce Champions (Platform Champions), a Computer Science graduate, working on the Salesforce platform and providing customer solutions using force.com as a Salesforce consultant/developer. He is the founder of SFDCLessons. :)

Leave a Reply