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
Kelly Logan (Raptek)Kelly Logan (Raptek) 

Batchable, Schedulable - getting 100% test coverage

Working on some legacy code that is using a combination of Batchable and Schedulable that seems odd. The original threw an error the last time we tried to schedule it - "Error: You must select an Apex class that has a parameterless constructor."

The original did indeed have a parameter
public static final Integer DEFAULT_BATCH_SIZE = 2000;
  global Integer batchSize;

  global ContactRollupsJob(Integer batchSize) {
    this.batchSize = batchSize;
  }
Given this seemed unnecessary, I tried creating a new version without the batch size set manually. I then noticed that there was no test code for this class, so I created that as well. The test runs successfully, but only provides 60% code coverage.  The lines not covered are the last ones in the class, the schedule and executeRollups methods. Any idea why these are not running? My next thought is that this Batchable, Schedulable mashup may not work anymore with current code and the best plan would be to split into a batch job called by a scheduled job.

Here is the new code
 
global class ContactRollupScheduled implements Database.Batchable<sObject>, Schedulable {
  public static final String CRON_EXP = '0 0 0/1 1/1 * ? *';

  global Database.QueryLocator start(Database.BatchableContext bc) {
    Id stRT = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Student').getRecordTypeId();
    return Database.getQueryLocator([SELECT Id,cohort__r.name,cohort__c 
                                     FROM Contact
                                     WHERE RecordTypeId=:stRT]);
  }

  global void execute(Database.BatchableContext bc, List<Contact> contacts) {
    contacts = StudentTermPaymentService.setRollupPaymentInformationForContacts(contacts);
    contacts = ContactService.setRollupTermEligibilityAndDevEdInformation(contacts);
    contacts = ContactService.setRollupEducationInformation(contacts);
    update contacts;
  }

  global void finish(Database.BatchableContext bc) {

  }

  global void execute(SchedulableContext sc) {
    Database.executeBatch(this);
  }

  global static String schedule(String cron) {
    if (cron == null) {
      cron = CRON_EXP;
    }
    ContactRollupScheduled job = new ContactRollupScheduled();
    return System.schedule('Contact Rollups Job', cron, job);
  }

  global static String executeRollups() {
    ContactRollupScheduled job = new ContactRollupScheduled();
    return Database.executeBatch(job);
  }

}
And the test class
@isTest
public with sharing class ContactRollupScheduled_test {

    public static testmethod void testScheduledJob() {
        
        // Create some Contact records
        List<Contact> cons = new List<Contact>();
        for (Integer i=0; i<10; i++) {
            Contact c = new Contact(LastName = 'Tester ' + i);
            cons.add(c);
        }
        insert cons;

        Test.startTest();
        // Schedule the test job
        String jobId = System.schedule('ScheduledApexTest',
            ContactRollupScheduled.CRON_EXP, 
            new ContactRollupScheduled());   
        CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered,
         NextFireTime
         FROM CronTrigger WHERE id = :jobId];
    System.assertEquals(ContactRollupScheduled.CRON_EXP,
         ct.CronExpression);

        System.debug('Scheduled Job ID: ' + jobId);
        // Stopping the test will run the job synchronously
        Test.stopTest();
        
    }
}



 
Kelly Logan (Raptek)Kelly Logan (Raptek)
Guess everyone's still on vacation. . . :^)
Kelly Logan (Raptek)Kelly Logan (Raptek)
The answer was to comment out those last two methods. They don't seem to be useful for this function. May have been part of some other system.