function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Marc FriedmanMarc Friedman 

Test Class for Scheduled Batch Apex not Working

Hi,

 

We have a Scheduler Class for a Batch Class, both of which are working fine as evidenced by the fact that they have both successfully fired on schedule the last three days.  The Test Class, however, seems to be written incorrectly / not invoking properly.  The text class is below:

 

@isTest

class TestStampForecastLastUpdated {
	
	static testMethod void testStampForecastLastUpdated() {
		
		// Declare Local Variables
		final string							accountRecordType = 'Distributor';
		Id										accountRecordTypeId;
		Map<String, Schema.RecordTypeInfo>		accountRecordTypes = new Map<String, Schema.RecordTypeInfo>();
		CronTrigger								cronTrigger;
		String 									jobId;
		final Date								monthEnd = date.valueOf('2008-02-29 00:00:00');
		final Date								today = System.today();
		Product2								product;
		
		// Get Account Record Type Ids
		accountRecordTypes = Schema.SObjectType.Account.getRecordTypeInfosByName();
		accountRecordTypeId = accountRecordTypes.get(accountRecordType).getRecordTypeId();

		// Create an Account
		Account a1 = new Account (Name = 'Acme', Product_Discount_Amount__c = 9, RecordTypeId = accountRecordTypeId);
		Insert a1;
		
		// Get a Product
		product = [SELECT Id FROM Product2 WHERE IsActive = true AND Forecast__c = true LIMIT 1];
		
		// Create a Forecast record in the past and one in the future
		Forecast__c f1 = new Forecast__c (Account__c = a1.id, Backlog_Quantity__c = 1, Backlog_Amount__c = 100, Est_Forecast_Rev__c = 100, Last_Updated__c = date.valueOf('2008-02-15 00:00:00'), Month_End_Date__c = monthEnd, Product__c = product.Id, Quantity__c = 1, Shipped__c = 1, Shipped_Amount__c = 100, Shipped_and_Backlog__c = 150);
		Forecast__c f2 = new Forecast__c (Account__c = a1.id, Backlog_Quantity__c = 1, Backlog_Amount__c = 100, Est_Forecast_Rev__c = 100, Last_Updated__c = date.valueOf('2008-02-15 00:00:00'), Month_End_Date__c = today, Product__c = product.Id, Quantity__c = 1, Shipped__c = 1, Shipped_Amount__c = 100, Shipped_and_Backlog__c = 150);
		insert f1;
		insert f2;
		
		// Execute the batchable test
		Test.startTest();

		// Schedule the test job
		String scheduleExpression = '0 0 0 3 9 ? 2022';
		jobId = System.schedule('testScheduleStampForecastLastUpdated', scheduleExpression, new ScheduleStampForecastLastUpdated());
		
		// Get the CronTrigger info
		cronTrigger = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];
		
		// Assert that the expressions are the same
		System.assertEquals(scheduleExpression, cronTrigger.CronExpression);
		
		// Assert that the Cron job has not started
		System.assertEquals(cronTrigger.TimesTriggered, 0);
		
		// Assert that the Forecasts have their original values
		System.assertEquals([SELECT Last_Updated__c FROM Forecast__c WHERE Id = :f1.Id].Last_Updated__c, date.valueOf('2008-02-15 00:00:00'));
		System.assertEquals([SELECT Last_Updated__c FROM Forecast__c WHERE Id = :f2.Id].Last_Updated__c, date.valueOf('2008-02-15 00:00:00'));
		
		// Stop the test
		Test.stopTest();
		
		// Assert that the Forecasts have their proper values
		System.assertEquals([SELECT Last_Updated__c FROM Forecast__c WHERE Id = :f1.Id].Last_Updated__c, date.valueOf('2008-02-15 00:00:00'));
System.debug('f2 = ' + [SELECT Status__c FROM Forecast__c WHERE Id = :f2.Id]);
		System.assertEquals([SELECT Last_Updated__c FROM Forecast__c WHERE Id = :f2.Id].Last_Updated__c, System.today());
	}
}

 

The last assertion fails, although the System.debug line shows that it should have been processed.  Again, the Scheduler and Batch are working properly, which leads me to believe that this Test Class is constructed improperly.

 

Relevant code from the Scheduler and Batch below, although again, they have fired properly as scheduled every day since scheduled.

 

global class ScheduleStampForecastLastUpdated implements Schedulable {

	global void execute (SchedulableContext sc) {

		stampForecastLastUpdated sflu = new stampForecastLastUpdated('SELECT Last_Updated__c FROM Forecast__c WHERE Status__c = \'Active\'');
		database.executebatch(sflu);
	}
}

 

global class StampForecastLastUpdated implements Database.Batchable<sObject>{

	global final string	query;
	date				today = date.today();

	global StampForecastLastUpdated(String query) {
		this.query = query;
	}
	
	global Database.QueryLocator start(Database.BatchableContext BC) {
		return Database.getQueryLocator(query);
	}

	global void execute(Database.BatchableContext BC, List<sObject> scope) {
		List<Forecast__c> forecasts = new List<Forecast__c>();

		for (sObject s : scope) {
			Forecast__c f = (Forecast__c)s;
			f.Last_Updated__c = today;
			forecasts.add(f);
		}
		update forecasts;
	}

	global void finish(Database.BatchableContext BC) {
	}
}

 

 

Thanks,

Marc

Ron WildRon Wild

Have you tried checking the TimesTriggered value after Test.stopTest() to confirm that the job is running.   I've run into a similar case where the job just doesn't seem to be firing.  Independent tests of the batch job I'm running with the Scheduled Apex indicate that the job is running without problems.

 

		cronTrigger = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];


// Assert that the Cron job has run once
System.assertEquals(cronTrigger.TimesTriggered, 1);
Marc FriedmanMarc Friedman

Hi Ron,

 

Thanks for your reply.  Checking TimesTriggered after stopTest indicates that the code is not firing.  You had mentioned running into situations in which the code does not appear to fire - have you been able to identify the common cause / situations where this is the case?

 

Thanks,

Marc

sfdc_Devlsfdc_Devl
Hi Marc/Ron,

Any update why this might not work? I am facing the same issue.
Eduardo De Souza 4Eduardo De Souza 4
you have to remove the testmethod from your method; otherwise, the changes inside your batch will not be committed. Of course, when the test ends, the rollback is done automatically: 
 
static void testStampForecastLastUpdated() { ... }

you should not use @isTest in this case as well. 
Saravanan Raju7Saravanan Raju7
Thank you @Eduardo De Souza 4
I unknowingly added TestMethod in my Test class to test batch/schedule and the record was not updating and assert failed, and your answer saved me lot! Thanks.