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