Test class for Batch Apex in Salesforce

Testing is critical component and Salesforce.com strongly recommends using a test-driven development process. Salesforce requires at least 75% of code to be covered by our test classes before the code is deployed to the production. Therefore understanding test class structure is important. In this article I have taken a scenario to write test class for batch apex.

Scenario

Write a test class for batch apex for inserting account and related contacts.

In this article I will go through:

  • Code Snippet for the given scenario
  • Test class terminology
  • Understanding Code line by line
  • Best Practices related to testing of batch apex

Code Snippet

@isTest
private class testbatchUpdateAccountContacts {
    @testSetup 
    static void setup() {
        List<Account> accounts = new List<Account>();
        List<Contact> contacts = new List<Contact>();
                
        // insert 200 accounts
        for (Integer i=0;i<200;i++) {
            
            accounts.add(new Account(name='Account '+i, 
                description ='Test', NumberOfEmployees=70));
        }
        insert accounts;
        // find the account just inserted. add contact for each
        for (Account account : [select id from account]) {
            contacts.add(new Contact(firstname='first', 
                lastname='Test', accountId=account.id));
        }
        insert contacts;
    }
        static testmethod void test() {        
        Test.startTest();
        batchUpdateAccountsContacts tb = new batchUpdateAccountsContacts();
        Id batchId = Database.executeBatch(tb);
        Test.stopTest();
            Integer con=[select count() from contact];
        // after the testing stops, assert records were inserted properly
        System.assertEquals(200, [select count() from contact]);
        System.assertEquals(200, [select count() from account]);
        }
}

Explaining code line by line

@isTest annotation

It is used to define classes and methods that only contain code used for testing our application.

@isTest

Advantage of writing a Test Class

Advantage of creating a separate class for testing is that classes defined with isTest don’t count against our organization limit of 6 MB for all Apex code.

private class testbatchUpdateAccountContacts {}

@testSetup annotation

Methods that are annotated with @testSetup are used to create test records once and then access them in every test method in the test class. I have created a Test setup method so as to create common test data so that I do not need to re-create records for each test method.

@testSetup

In the below method I create 200 account and related contact records and then insert them in the list (accounts) and (contacts) respectively.

static void setup() {
        List<Account> accounts = new List<Account>();
        List<Contact> contacts = new List<Contact>();
                
        // insert 200 accounts
        for (Integer i=0;i<200;i++) {
            
            accounts.add(new Account(name='Account '+i, 
                description ='Test', NumberOfEmployees=70));
        }
        insert accounts;
        // find the account just inserted. add contact for each
        for (Account account : [select id from account]) {
            contacts.add(new Contact(firstname='first', 
                lastname='Test', accountId=account.id));
        }
        insert contacts;
    }

Test Method Name

A test method is defined as static testMethod void testMethodName()

        static testmethod void test() {}      

Here I have executed the batch class between Test.startTest and Test.stopTest so as to

ensure that any asynchronous transactions finish executing before Test.stopTest() exits.

startTest()

Marks the point in our test code when our test actually begins. Each test method is allowed to call this method only once.

Test.startTest();

stopTest()

Marks the point in our test code when our test ends. Each test method is allowed to call this method only once. Any code that executes after the stopTest method is assigned the original limits that were in effect before startTest was called.

Test.stopTest();

Database.ExecuteBatch

Create instance of the batch class and execute the class by writing Database.executeBatch and pass instance of the class inside it.

batchUpdateAccountsContacts tb = new batchUpdateAccountsContacts();
        Id batchId = Database.executeBatch(tb);

System.AssertEquals

It accepts three parameters; the first two are the variables that will be tested for equality or inequality, and the third (optional) one is used to display a message in case the condition fails.

Here I am checking the count of contact and account are equal to 200 by using system.assertEquals()

System.assertEquals(200, [select count() from contact]);
 System.assertEquals(200, [select count() from account]);

Best Practices

  • We should always test batch class with good amount of data (minimum 200 records) in our test class.
  • We must execute the batch class between Test.StartTest() and Test.StopTest().

Write more test classes and enhance your learning. I hope you enjoyed this article. For more of these kind of articles stay tuned.

Happy Coding!

https://trailhead.salesforce.com/en/content/learn/modules/asynchronous_apex

https://developer.salesforce.com/docs/atlas.en-us.218.0.apexcode.meta/apexcode/apex_batch_interface.htm

https://developer.salesforce.com/docs/atlas.en-us.210.0.apexcode.meta/apexcode/apex_qs_test.htm

Did you enjoy this article?
Signup today and receive free updates straight in your inbox.
I agree to have my personal information transfered to MailChimp ( more information )
50% LikesVS
50% Dislikes