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
kdaviskdavis 

Testing scheduled batch job

Hi,

 

I am running a scheduled batch job where I perform the DML operation inside the finish method. I placed a debug log inside the finish method to print out my records to see if everything is updating the values correctly and it does, and from the test log I see that it performs the update as well.

 

Now the problem is, after I do my Start.Test() and Stop.Test() where I schedule my class to run and set up data, I query the objects I have updated and print them out nothing happens to them....

 

When I look at the execution in the test log, the print outs in my test method are occuring before my debugs in both my execute and finish methods.

 

Am I missing something here? It looks as if my assertions and debugs are occurring before the fact rather than after and I'm not quite sure how to fix it.

 

Any feedback would be appreciated.

Thanks

souvik9086souvik9086

What is the issue coming? Is the test method not covering much or not?

Is your batch apex executing properly?

 

Thanks

kdaviskdavis

I get 100% coverage. I can post the code if you want but for now here is my test class so I can explain a little better

 

@isTest
private class testEmailCount {
	
	@isTest static void test_method_one() {

		RecordType rtype = [SELECT Id, Name FROM RecordType WHERE Name = 'Support Case'];

		Case c = new Case(
			RecordTypeID = rtype.Id,
			Disposition_Code__c = 'Consultants',
			Disposition_Status__c = 'Open',
			Disposition_Reason__c = 'Consultant event approval',
			Status = 'New',
			Origin = 'Email'
		);
		insert c;

		Task t = new Task(
			WhatId = c.Id,
			ActivityDate = Date.today().addDays(-4),
			Subject = 'Email:Send me an email',
			Description = 'Blah Blah Blah This is the canned Text blah blah blah'
		);
		insert t;

		QuickText qt = new QuickText(
			Name = 'Test',
			Message = 'This is the canned Text',
			Category = 'Greetings'
		);
		insert qt;

	test.starttest();
		
		emailCountScheduled ecs = new emailCountScheduled();        
		String sch = '0 0 23 * * ?';        
		String jobId = system.schedule('Email Counts', sch, ecs);

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

        System.assertEquals(sch, 
        ct.CronExpression);

	test.stopTest();

		QuickText q = [SELECT Total_Use_1_Day__c, Total_Use_30_Days__c, Total_Use_7_Days__c, Id FROM QuickText WHERE Id =: qt.Id];

		System.debug('30***********************************   '+ q.Total_Use_30_Days__c);
		System.debug('7***********************************   '+ q.Total_Use_7_Days__c);
		System.debug('1***********************************   '+ q.Total_Use_1_Day__c);

	}
}

 Those last three debugs from the debug log seem like they are occurring before my execute and finish method even happen. Because I see the records that are suppose to be inserted have the correct values and I see that 1 row has been inserted. But I get the wrong values inside those print outs

kdaviskdavis

I'll just post the code as well.

 

Scheduled Class:

global class emailCountScheduled implements Schedulable{


	global void execute(SchedulableContext sc) {

		List<QuickText> qt = new List<QuickText> ();
		Map<String, QuickText> responseToQT = new Map<String, QuickText> ();
		List<String> messages = new List<String> ();
		Date dateFilter = Date.Today().addDays(-30);
		String dateFilterString = String.valueOf(dateFilter);

		qt = [SELECT Id, Message, Total_Use_1_Day__c, Total_Use_30_Days__c, Total_Use_7_Days__c FROM QuickText];

		if(!qt.isEmpty()){
			for(QuickText q : qt){
				if(q.Message != null){
					messages.add(q.Message);
					q.Total_Use_1_Day__c = 0;
					q.Total_Use_7_Days__c = 0;
					q.Total_Use_30_Days__c = 0;
					responseToQT.put(q.Message, q);
				}
			}
		}

		String query = 'SELECT Id, Subject, Description, ActivityDate FROM task WHERE Subject LIKE \'%Email%\' AND ActivityDate > dateFilter';
		query = query.replace('dateFilter', dateFilterString);

		emailCountBatch b = new emailCountBatch(responseToQT,messages,query);

		database.executebatch(b);
	}
}

 Batch class

global class emailCountBatch implements Database.Batchable<sObject>, Database.Stateful {
	
	global final String query;
	global final List<String> cannedResponses;
	global Map<String, QuickText> responseObjects;

	global emailCountBatch(Map<String, QuickText> qt, List<String> messages, String q) {

		responseObjects = qt; cannedResponses = messages; query = q;

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

   	global void execute(Database.BatchableContext BC, List<sObject> scope) {
	   	Map<String, List<sObject>> thirtyDays = new Map<String, List<sObject>> ();
		Map<String, List<sObject>> sevenDays = new Map<String, List<sObject>> ();
		Map<String, List<sObject>> oneDay = new Map<String, List<sObject>> ();

		for(sObject s : scope){

			String emailBody = String.ValueOf(s.get('Description'));

			for(String m : cannedResponses){
				if(emailBody.contains(m)){
					if(!thirtyDays.containsKey(m)){
						thirtyDays.put(m, new List<sObject> ());
					}

					if(thirtyDays.containsKey(m)){
						List<sObject> objectList = thirtyDays.get(m);
						objectList.add(s);
						thirtyDays.put(m, objectList);
					}

					//Check if within 7 days
					if(Date.ValueOF(s.get('ActivityDate')) > Date.Today().addDays(-7)){
						if(!sevenDays.containsKey(m)){
							sevenDays.put(m, new List<sObject> ());
						}

						if(sevenDays.containsKey(m)){
							List<sObject> objectList = sevenDays.get(m);
							objectList.add(s);
							sevenDays.put(m, objectList);
						}						
					}

					//Check if within 1 day
					if(Date.ValueOF(s.get('ActivityDate')) > Date.Today().addDays(-1)){
						if(!oneDay.containsKey(m)){
							oneDay.put(m, new List<sObject> ());
						}

						if(oneDay.containsKey(m)){
							List<sObject> objectList = oneDay.get(m);
							objectList.add(s);
							oneDay.put(m, objectList);
						}						
					}					
				}
			}
		}

		for(String s : responseObjects.keySet()){
			QuickText currentQT = responseObjects.get(s);
			if(thirtyDays.get(s) != null){
				system.debug('Entered30');
				currentQT.Total_Use_30_Days__c += thirtyDays.get(s).size();
			}
			if(sevenDays.get(s) != null){
				system.debug('Entered7');
				currentQT.Total_Use_7_Days__c += sevenDays.get(s).size();
			}
			if(oneDay.get(s) != null){
				system.debug('Entered1');
				currentQT.Total_Use_1_Day__c += oneDay.get(s).size();
			}

			responseObjects.put(s, currentQT);
		}

	}
	
	global void finish(Database.BatchableContext BC) {

		system.debug('OBjects    '+responseObjects);
		update responseObjects.values();
	}
}

 I need to pull all emails and count how many with text matching a quick text message have occurred in the last 30,7, and 1 days. So I need to use a batchable state that continuously updates the counts on the quick text object then update in the finish method.

But my debugs aren't matching up :/

kdaviskdavis

After further investigation,

It appears the test method completes before the execute and finish method in the batch class even fire. Do I need to specifically call out the batch class in the test method even though it's called in the scheduled class? Both execute and finish methods but completely after the test method.