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
loislaneloislane 

Help with Test Case for Apex class that will email reminders and run on a schedule

new to Apex so please be patient

 

 

wrote this simple apex reminder class that appears to work in DEV. now need to get to Prod.

 

I need assistance writing a test class as well as getting it to production.

 

//public class myRenewalDateNotify{

//  public static void sendRenewalNotify(){
global class AccountRenewalDateNotify implements System.Schedulable {

  global void execute (SchedulableContext sc) {

      
    List<Account> accts=[SELECT Id,Name,Renewal_Date__c from Account WHERE Renewal_Date__c = Today ORDER BY Name];
  if (!accts.IsEmpty()){
        // send email notification    
   
    Date myDate = Date.Today();
    String sDate = String.valueOf(myDate);        
       String htmlbody;
       integer i = accts.size();
system.debug(i +' accounts are set for renewal today: '+sDate);    

        // Now create a new single email message object 
        // that will send out a single email to the addresses in the To, CC & BCC list. 
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
system.debug('set new mail msg');

        // Strings to hold the email addresses to which you are sending the email. 
//        String[] toAddresses = new String[] {'user1@mydomain.com'};
        String[] toAddresses = new String[] {'user3@mydomain.com'};

system.debug('set toAddress');
        String[] ccAddresses = new String[] {'user2@mydomain.com','user1@mydomain.com'};
system.debug('set ccAddress');
  
        // Assign the addresses for the To and CC lists to the mail object. 
              mail.setToAddresses(toAddresses);
              mail.setCcAddresses(ccAddresses);
system.debug('assign email To & cc');

        // Specify the address used when the recipients reply to the email.  
            mail.setReplyTo('noreply@mydomain.com');
system.debug('set replyTo');

        // Specify the name used as the display name. 
            mail.setSenderDisplayName('Salesforce Account Renewal Notices');
system.debug('set display name');

        // Specify the subject line for your email. 
         mail.setSubject('SFDC Account Renewals for Today : ' + sDate);
system.debug('set subject');
       
         // loop through and build email body       
system.debug('start accts loop');
    
        for(Account a : accts){
            //String fullRecordURL = URL.getSalesforceBaseUrl().toExternalForm() + '/' + acct.Id;        
            //htmlbody = (htmlbody+'<a href=https://na1.salesforce.com/'+a.Id+'>'+a.Name+'</a><p>');
            // Get the base URL. 
    
            String sfdcBaseURL = URL.getSalesforceBaseUrl().toExternalForm();
System.debug('Base URL: ' + sfdcBaseURL );       
system.debug('Account:'+a.Name);
 
            if (htmlbody==null){
              htmlbody = ('<a href='+sfdcBaseURL+'/'+a.Id+'>'+a.Name+'</a><p>');
            } else {
              htmlbody = (htmlbody+'<a href='+sfdcBaseURL+'/'+a.Id+'>'+a.Name+'</a><p>');
            }  
         }

system.debug(htmlbody);
         
         mail.setHtmlBody('The following SFDC Accounts are set for renewal today:<p>'+htmlbody);

system.debug('send email');
        // Send the email you have created. 
         Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });         
system.debug('success');
         
   }
  }
}

 

crop1645crop1645

There are three parts to resolve this:

 

1. Break your code into a simple class that implements the schedulable interface and a separate class / method that does all the work inside your execute statement

 

2. Then you can easily write a test method on the second class/method and not worry about the schedulable class testing

 

3. To test the schedulable class, you need something like this:

 

  static testmethod void testAccountRenewalDateNotify() {

      
    
  
    String    CRON_EXP = '0 0 0 3 9 ? 2022';    // midnight sep 3, 2022 -- for testing purposes only
    
    Test.startTest();
    
    String    jobId    = System.schedule('Test AccountRenewalDateNotify',CRON_EXP,new AccountRenewalDateNotify());
    CronTrigger ct       = [SELECT id, CronExpression, TimesTriggered,NextFireTime FROM CronTrigger WHERE id = :jobId];
    System.assertEquals(CRON_EXP,ct.CronExpression);              // verify scheduled at right time
    System.assertEquals(0, ct.TimesTriggered);                  // verify not yet executed
    System.assertEquals('2022-09-03 00:00:00',String.valueOf(ct.NextFireTime));  // verify when it will next execute
    
    Test.stopTest();    // this will cause the scheduled job to run
    

    
    
  }

 Admittedly, I took this from my system where the execute method invokes a class that implements the batchable interface as I was doing scheduled updates.

 

Note that there is a governor limit on the # of emails you can send per day

 

Note also that emails will not be sent in dev/sandbox orgs when invoked by testmethods