Tag Archives: Test Class

Salesforce Schedulable Apex Test Class

Batch Class:

global class AccountBatch implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC){
        String query = 'SELECT Id, Name, Industry FROM Account';                
        return Database.getQueryLocator(query);     
    }
    
    global void execute(Database.BatchableContext BC, List<Account> accList){        
        for(Account acc : accList){          
            acc.Industry = 'Banking';        
        }        
        update accList;       
    }
    
    global void finish(Database.BatchableContext BC) {
        
    }
}

Schedulable Class:

global class AccountBatchScheduled implements Schedulable {
    
    global void execute(SchedulableContext sc) {
        AccountBatch objBatch = new AccountBatch(); 
        Database.executebatch(objBatch);
    }
}

Test Class:

@isTest
private class AccountBatchScheduledTest{
    
    static testmethod void schedulerTest(){
        
        String cronexpression = '0 0 0 15 3 ? *';

        Account acc = new Account();
        acc.Name = 'Test Account';
        Insert acc;
        
        Test.startTest();
        String jobId = System.schedule('ScheduleBatchApexClass',  cronexpression, new AccountBatchScheduled());
        CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
        System.assertEquals(cronexpression, ct.CronExpression);
        System.assertEquals(0, ct.TimesTriggered);
        Test.stopTest();
    }
}

Best Practice for Test Classes in Salesforce

  • To deploy to production at-least 75% code coverage is required, But your focus shouldn’t be on the percentage of code that is covered. Instead, you should make sure that every use case of your application is covered, including positive and negative cases, as well as bulk and single records. This should lead to 75% or more of your code being covered by unit tests.
  • Test class must start with @isTest annotation if class version is more than 25.
  • @isTest annotation with test method  is equivalent to testMethod keyword.
  • Test class and method default access is private ,no need to add access specifier.
  • Classes with @isTest annotation can’t be a interface or enum.
  • Test method code can’t be invoked by non test request.
  • Stating with salesforce API 28.0 test method can not reside inside non test classes.
  • Always use @testSetup method dedicated to create test records for that class. This is newly added annotation and very powerful.
  • If possible Don’t use seeAllData=true, Create your Own Test Data. SeeAllData=true will not work for API 23 version earlier.
  • User, profile, organization, AsyncApexjob, Corntrigger, RecordType, ApexClass, ApexComponent ,ApexPage we can access without (seeAllData=true).
  • @TestVisible annotation can be used to access private members and methods inside Test Class. Now we don’t need to compromise with access specifiers for sake of code coverage.
  • Test method and test classes are not counted as a part of code limit.
  • Test method takes no argument, commit no data to database, send no email, flagged with testMethod keyword.
  • Use Test.startTest() to reset Governor limits in Test methods.
  • If you are doing any Asynchronous operation in code, then don’t forget to call Test.stopTest() to make sure that operation is completed.
  • Use System.runAs() method to enforce OWD and Profile related testings. This is very important from Security point of View.
  • System.runAs() will not enforce user permission or field level permission.
  • Use As much as Assertions like System.AssertEquals or System.AssertNotEquals.
  • Always test Batch Capabilities of your code by passing 20 to 100 records.
  • Always try to pass null values in every methods. This is the area where most of program fails, unknowingly.
  • Please use call out mock to test web-service call out .
  • System.debug statement are not counted as a part of apex code limit.
  • We can run unit test by using Salesforce Standard UI,Force.com IDE ,Console ,API.
  • Maximum number of test classes run per 24 hour of period is  not grater of 500 or 10 multiplication of test classes of your organization.

Salesforce: Create Test Data for Group and GroupMember Objects in Test Class

Sample Test Class:

@isTest
global class SampleTestClass
{
	public static TestMethod void TestSampleMethod()
	{
		Test.startTest();     

		//Create Parent Group
		Group grp = new Group();
		grp.name = 'Test Group1';
		grp.Type = 'Regular'; 
		Insert grp; 

		//Create Group Member
		GroupMember grpMem1 = new GroupMember();
		grpMem1.UserOrGroupId = UserInfo.getUserId();
		grpMem1.GroupId = grp.Id;
		Insert grpMem1;

		//Create Sub group
		Group subGrp  = new Group();
		subGrp.name = 'Test Group2';
		subGrp.Type = 'Regular'; 
		Insert subGrp; 

		//Assign Role To Parent Group
		GroupMember grpMem2 = new GroupMember();
		grpMem2.UserOrGroupId = subGrp.Id;
		grpMem2.GroupId = grp.Id;
		Insert grpMem2;  

		//Create Group Map Data
		Map<String,Id> groupNameRoleIdMap = new Map<String,Id>();
		for(Group gp: [SELECT Id, Name FROM Group WHERE Type = 'Role']){
			groupNameRoleIdMap.put('SuperAdmin', gp.Id);
		}     

		//Assign role to parent group
		GroupMember grpMem3 = new GroupMember();
		grpMem3.UserOrGroupId = groupNameRoleIdMap.get('SuperAdmin');
		grpMem3.GroupId = grp.Id;
		Insert grpMem3; 

		//Create Group And Sub Group Map Data
		Map<String,Id> groupNameRoleAndSubordinatesIdMap = new Map<String,Id>();
		for(Group gp: [SELECT Id, Name FROM Group WHERE Type = 'RoleAndSubordinates']){
			groupNameRoleAndSubordinatesIdMap.put('Admin', gp.Id);
		} 

		//Assign Role To Parent Group
		GroupMember grpMem4 = new GroupMember();
		grpMem4.UserOrGroupId = groupNameRoleAndSubordinatesIdMap.get('Admin');
		grpMem4.GroupId = grp.Id;
		Insert grpMem4;             
		
		//Execute your method here with Group and Group Member Test data
		
		Test.stopTest();
	}
}

Test Setup Method in Salesforce Apex

In Spring ’15 release Salesforce has introduced new @testSetup annotation for Test class method. @testSetup annotation defined methods are used for creating common test records, and that records are available for all test methods in the class.

@testSetup methods create common test data easily and efficiently, and reduce test execution times especially when we are working with many records.

Example:

@iSTest
private class AccountControllerTest {
    
    //Test Setup Method
    @testsetup
    static void createAccount() {
        Account acc = new Account();
        acc.Name = 'Salesforce';
        insert acc;
    }
    
    //Test Method
    public static testMethod void test() {
        System.assertEquals(1, [SELECT COUNT() FROM Account Where Name = 'Salesforce']);
    }
}

Considerations:

  • Records created by @testSetup method are available to all test methods in the test class.
  • @testSetup methods are executed first in the test class before any test methods.
  • One Test class can have only one @testSetup method. If multiple @testSetup method is written in a Test class then sequence of execution of those methods are not guaranteed.
  • If the test class or a test method has access to organization data by using the @isTest(SeeAllData=true) annotation, test setup methods aren’t supported in this class.
  • If any error occurss during the execution in @testSetup method, then entire test class fails.
  • The data created by @testSetup methods will be rolled back after the completly execution of the test class.
  • If a test setup method calls a non-test method of another class, no code coverage is calculated for the non-test method.

Test Class for Batch Apex in Salesforce

Batch Class:

global class BatchAccount implements Database.Batchable<sObject> 
{
    global Database.QueryLocator start(Database.BatchableContext BC) {
		
        return Database.getQueryLocator('SELECT Id,Name FROM Account');
    }
	
    global void execute(Database.BatchableContext BC, List<Account> scope) {
		
        for(Account a : scope)
        {
            a.Name = a.Name + ' Updated';
        }
        update scope;
    }
	
    global void finish(Database.BatchableContext BC) {
		
    }
}

Test Class:

@isTest 
public class BatchAccountTest 
{
    static testMethod void test() 
    {
        List<Account> accList = new List<Account>();
        for(Integer i = 0 ; i < 200; i++)
        {
            Account acc = new Account();
            acc.Name = 'Name' + i;
            accList.add(acc);
        }
        Insert accList;
        
		Test.startTest();
		BatchAccount obj = new BatchAccount();
		DataBase.executeBatch(obj); 
		Test.stopTest();
		
		//Verify accounts updated
		List<Account> accUpdatedList = [SELECT Id, Name FROM Account];
		System.assert(accUpdatedList[0].Name.Contains('Updated'));
    }
}