3

I am testing a batch file which just changes the field value of records in scope and updates them:

global class AbatchClass implements Database.Batchable<sObject>{

   global String query;
   global AbatchClass (){   
   query = 'SELECT Id,Name,status__c FROM obj__c where status__c = \'active\' ';

   }

   global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);

   }

   global void execute(Database.BatchableContext BC, List<obj__c> scope){
     List<obj__c> objToBeUpdated = new List<obj__c>();
     for(obj__c o: scope){
     o.status__c='Inactive';
     objToBeUpdated.add(o);
     }
     update objToBeUpdated;
    }

   global void finish(Database.BatchableContext BC){
   system.debug('****************Start Finish********************');
     system.debug('****************Exit Finish********************');
   }

My Apex test method:

@isTest
    static void testifEmployeesAreInactive(){

           List<obj__c> objList = new List<obj__c>();
  for(Integer i=0;i<20;i++){ 
      obj__c o = new obj__c (Name='Test'+i,Status__c='Active');
      objList.add(emp);
  }
  Insert objList;

      Test.startTest();

      AbatchClass batchJob = new  AbatchClass();
      Database.executebatch(batchJob);
      List<obj__c> exsistingListInactive = [select id,status__c from obj__c where     status__c = 'inactive'];     
      system.assertequals(exsistingList.size(),0); // this succeeds

      List<obj__c> exsistingListActive = [select id,employee_status__c from employees__c where employee_status__c = 'active'];     
      System.assertequals(exsistingList1.size(),0); // this fails, says expected is 20 and actual is 0

      Test.stopTest();  

    }

So basically batch job makes the status field on the records as inactive and updates them. But when I check this through test class my both assertions are failing which means when running from test class the batch is not updating the records. Anything I am missing here?

2 Answers 2

6

Batch class start(), execute() and finish() do not actually execute until SFDC has reached the Test.stoptest(). Thus, your queries and asserts need to occur after the Test.stopTest().

Test.stoptest() causes all asynchronous tasks to execute.

The executeBatch method starts an asynchronous process. When you test batch Apex, make certain that the asynchronously processed batch job is finished before testing against the results. Use the Test methods startTest and stopTest around the executeBatch method to ensure that it finishes before continuing your test. All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously. If you don’t include the executeBatch method within the startTest and stopTest methods, the batch job executes at the end of your test method. This execution order applies for Apex saved using API version 25.0 and later, but not for earlier versions.

2
  • Thanks. Learned. In general(when not batch class) does the assertions have to be done only after stoptest() ?
    – SfdcBat
    Commented Aug 31, 2016 at 21:04
  • 1
    @SfdcBat You can use assertions anywhere you want, as frequently as you need to make sure your business logic is intact. Generally speaking, most assertions will "generally" occur after Test.stopTest(), but there's no hard and fast rule saying you must.
    – sfdcfox
    Commented Aug 31, 2016 at 21:08
5

The batch job won't actually be executed until Test.stopTest() is called. Move that line up above your assertions.

From Using Batch Apex - Testing Batch Apex, my emphasis.

The executeBatch method starts an asynchronous process. When you test batch Apex, make certain that the asynchronously processed batch job is finished before testing against the results. Use the Test methods startTest and stopTest around the executeBatch method to ensure that it finishes before continuing your test. All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously. If you don’t include the executeBatch method within the startTest and stopTest methods, the batch job executes at the end of your test method

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .