The call to Database.executeBatch should be included within the Test.startTest and Test.stopTest block. The job executes after the call to Test.stopTest. Any asynchronous code included within Test.startTest and Test.stopTest is executed synchronously after Test.stopTest.
Sample Batch Apex:
global class AccountBatch Implements Database.Batchable <sObject> {
global Database.queryLocator start( Database.BatchableContext bc ) {
String SOQL = ‘SELECT Id, Industry FROM Account’;
return Database.getQueryLocator(SOQL);
}
global void execute( Database.BatchableContext bc, List < Account > listAccounts ) {
for ( Account objAct : listAccounts ) {
objAct.Industry = ‘Energy’;
}
update listAccounts;
}
global void finish( Database.BatchableContext bc ) {
AsyncApexJob a = [ SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedById
FROM AsyncApexJob
WHERE Id =: bc.getJobId() ];
Messaging.SingleEmailMessage batchEmail = new Messaging.SingleEmailMessage();
batchEmail.setTargetObjectId( a.CreatedById );
batchEmail.setSubject( ‘Asset Delete Batch ‘ + a.Status );
batchEmail.setPlainTextBody( ‘Jobs processed ‘ + a.JobItemsProcessed + ‘ with ‘+ a.NumberOfErrors + ‘ failures.’ );
batchEmail.setSaveAsActivity( false );
Messaging.sendEmail( new Messaging.SingleEmailMessage[] { batchEmail } );
}
}
Sample Test class:
@isTest
private class AssetDeleteBatchTest {
static testMethod void testAssetsDel() {
List < Account > insertAcc = new List< Account >();
for ( Integer a = 0; a < 3; a++ ) {
Account acc = new Account( Name = ‘Test Account’ + String.valueOf( a ), Industry = ‘Biotechnology’ );
insertAcc.add( acc );
}
insert insertAcc;
Test.startTest();
AccountBatch obj = new AccountBatch();
Database.executeBatch( obj );
Test.stopTest();
/*
Once Test.stopTest() hits, the batch job runs synchronously.
Once the batch job execute method is completed, the below codes are executed.
*/
List < Account > listAccounts = [ SELECT Id FROM Account WHERE Industry = ‘Energy’ ];
system.assertEquals( 3, listAccounts.size() );
}
}