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
SeanGormanSeanGorman 

Scheduled Batch Apex Test Coverage Problem

I think that testing batchcode is difficult and now I am scheduling it my tests are just not good.

 

I have a batchable class that takes transcripts of new users create the previous day and assigns to them, according to some rules, new learning objectives.

 

The new users are created by integration to back end systems. A trigger on insert  calls a future method which goes out to the vendor webservice to get a license. I cannot add this routine to that process as I need to fire it in batch in case we hire too many people at once. So a schedule it has to be. (assertion)

 

Here is the schedule controller: (basically cribbed from force.com examples)

 

global class Schedulable_RunAssignmentRules implements Schedulable{

	public static String CRON_EXP = '0 0 2 * * ? *';


	global static String scheduleIt() 
	{
		Schedulable_RunAssignmentRules SRAR = new Schedulable_RunAssignmentRules();
		return System.schedule('New User On-boarding', CRON_EXP, SRAR);
	}

	global void execute(SchedulableContext sc)
    {
		set<id> setTrainees = new set<id>();
		for (lmscons__Transcript__c lT : [select lmscons__Trainee__c from lmscons__Transcript__c where CreatedDate >= :system.today()-1])
		{	
	        setTrainees.add(lT.lmscons__Trainee__c);
	    }

//	    system.debug('setTrainees ' + setTrainees);
		if( setTrainees.size() > 0)
		{
        	RunAssignmentRules(setTrainees);
		}
    }

	public static void RunAssignmentRules(set<id> setTrainees)
	{
		database.executeBatch(new RunAssignmentRulesBatch(setTrainees), 30 );
	}
}

 

An excerpt of the head of the batchable class:

global class RunAssignmentRulesBatch implements Database.Batchable<sObject>, Database.Stateful, Database.AllowsCallouts {

global final string strQuery; global final set<id> Trainees; public RunAssignmentRulesBatch(set<id> Trainees) { system.debug('Trainees '+Trainees); this.Trainees = Trainees; if (system.Test.isRunningTest()) { this.strQuery = 'SELECT Id FROM User WHERE Id = \'' + UserInfo.getUserId() + '\' LIMIT 1'; } else { this.strQuery = 'SELECT u.Id, u.Department, u.Division from User u where u.ID in :Trainees and u.ContractorY_N__c = FALSE and u.IsActive=TRUE'; system.debug('strQuery constructor'+strQuery); } } global Database.QueryLocator start(Database.BatchableContext BC) { system.debug('strQuery start'+strQuery); return Database.getQueryLocator(strQuery); } global void finish(Database.BatchableContext BC) { } global void execute(Database.BatchableContext BC, list<User> Trainees) {         system.debug('Trainees in addAssignmentBatch '+Trainees);

 

And the test class

 

@isTest
private class RunAssignmentRulesTest {

	static testMethod void myUnitTest() {

		Profile profile = [select id, Name from profile where name='System Administrator'];

		list<lmscons__Curriculum__c> currList = new list<lmscons__Curriculum__c>();
		lmscons__Curriculum__c curr1 = new lmscons__Curriculum__c(Name = 'Test On-boarding Program First', Type__c = 'Curriculum');
		lmscons__Curriculum__c curr2 = new lmscons__Curriculum__c(Name = 'Test On-boarding Program Second', Type__c = 'Curriculum');
		currList.add(curr1);
		currList.add(curr2);
		insert currList;

		List<Assignment_Rule__c> obcsList = new List<Assignment_Rule__c>();
		Assignment_Rule__c obcs = new Assignment_Rule__c(All_Unit_Departments__c = TRUE, User_Departments__c = '', User_Business_Unit__c='Test Div', Curriculum__c=curr2.ID);
		Assignment_Rule__c obcsb = new Assignment_Rule__c(All_Unit_Departments__c = FALSE, User_Departments__c = 'Test DeptB', User_Business_Unit__c='Test DivB', Curriculum__c=curr2.ID);
		Assignment_Rule__c obcsc = new Assignment_Rule__c(New_Staff__c = TRUE, All_Unit_Departments__c = FALSE, Curriculum__c=curr2.ID );
		obcsList.add(obcs);
		obcsList.add(obcsb);
		obcsList.add(obcsc);
		insert obcslist;

		Test.startTest();
			List<User> UserList = new List<User>();
			User u1 = new User(alias = 'ts01', email='testtest01@test.com', emailencodingkey='UTF-8', lastname='testtest01', languagelocalekey='en_US', Department='Test Dept', Division='Test Div',
				localesidkey='en_US', profileid = profile.Id, timezonesidkey='America/Los_Angeles', username='testtest11@test343SF111112d.com', lmscons__Cornerstone_ID__c='newtest test12'
			);
			User u2 = new User(alias = 'ts02', email='testtest01@test.com', emailencodingkey='UTF-8', lastname='testtest01', languagelocalekey='en_US', Department='Test DeptB', Division='Test DivB',
				localesidkey='en_US', profileid = profile.Id, timezonesidkey='America/Los_Angeles', username='testtest12@test343SF111112d.com', lmscons__Cornerstone_ID__c='newtest test11'
			);
			UserList.add(u1);
			UserList.add(u2);
			insert UserList;
	
			// Schedule the test job
			String jobId = System.schedule('Prepare learning for new Users',
			Schedulable_RunAssignmentRules.CRON_EXP, 
	        new Schedulable_RunAssignmentRules());
	
	   // Get the information from the CronTrigger API object
			CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered,  NextFireTime FROM CronTrigger WHERE id = :jobId];
	
	   // Verify the expressions are the same
	      	System.assertEquals(Schedulable_RunAssignmentRules.CRON_EXP, 
			ct.CronExpression);
	
       // Verify the job has not run
            System.assertEquals(0, ct.TimesTriggered);

            String runDate =  string.Valueof(system.today()+1);

            list<lmscons__Transcript_Line__c> Lines = ([Select id, lmscons__Trainee__c, lmscons__Curriculum_Assignment__c from lmscons__Transcript_Line__c where lmscons__Trainee__c = :curr2.id]);
            if(lines.size() > 0)
            {
                list<lmscons__Curriculum_Assignment__c> assigns = ([Select id, lmscons__Curriculum__c from lmscons__Curriculum_Assignment__c where id = :Lines[0].id]);
            }
       // Verify the next time the job will run Lines
            System.assertEquals(runDate.abbreviate(11) + ' 02:00:00'  , String.valueOf(ct.NextFireTime));
            System.assertNotEquals('Test On-boarding Program Second', [select id, name from lmscons__Curriculum__c where id = :assigns[0].id].name);
    
        Test.stopTest(); System.assertEquals('testScheduledApexFromTestMethodUpdated', [SELECT id, name from lmscons__Curriculum__c WHERE id = :curr2.id].Name); } }

 

My issue is that I need to assert that new users have been created, that the transcript was created and that nothing was assigned... but doing that should make a failure as there will be nothing and the index into the array doesn't exist.

 

How can I clean up the test class so that I can assert something that makes sense?