+ Start a Discussion
CindyCindy 

Test class for schedulable apex sending email with list of opportunities

Hi please help me write a test class for a schedulable apex class that sends an email to all users who have a checkbox on their user checked.
 
//Send email to users where receive Grants email = TRUE
public class NoActivityThisQrtr implements Schedulable {
    public void execute(SchedulableContext sc) {
        // Get list of opportunities where the opps> account last activity date not in the current quarter
        List<Opportunity> listOfnoactivityOps = [Select Id, Name, StageName ,Account_Name__c,Accouint_Last_Activity_Date__c
                                             From Opportunity 
                                             Where Accouint_Last_Activity_Date__c != THIS_FISCAL_QUARTER];
        
        // Get user ids in a list
        User adminProfile = [Select Id From User Where Receive_TB_Grant_Emails_Notifications__c = TRUE];
        List<Id> listOfUserIds = new List<Id>();
        for(User usr : [Select Id From User Where ProfileId = :adminProfile.Id]) {
            listOfUserIds.add(usr.Id);
        }
        
        // Get all the opportunities Name, StageName, Acccount and Account Last Activity Date in a String
        String closedOpportunities = 'Opportunity Name' + ' : ' + 'Stage' + ':' +'Account' + ':' +'Account Last Activity Date';
        for(Opportunity op : listOfnoactivityOps) {
            closedOpportunities = ClosedOpportunities + '\n' + op.Name + ' : ' + op.StageName + ':' + op.Account_Name__c +':' + OP.Accouint_Last_Activity_Date__c;
        }
        
        sendmail(listOfUserIds, closedOpportunities);
    }
    
    public void sendmail(List<Id> listOfUserIds, String closedOpportunities) {
        // Creating instance of email and set values
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setToAddresses(listOfUserIds);
        email.setSubject('Accounts without Activity this month');
        email.setPlainTextBody( 'Hello, Here are opportunities whose accounts havent had activity this quarter'+ 
            closedOpportunities);
        
        // Send email
        Messaging.sendEmail(new List<Messaging.SingleEmailMessage> {email});
    }
}

this is the test class i have, no errors but also no coverage
 
@isTest
private class NoActivityThisQrtrTest
{
    static testmethod void schedulerTest() 
    {
        String CRON_EXP = '0 0 0 15 3 ? *';
        
        // Create your test data
        List<Opportunity> listOfnoactivityOps = [Select Id, Name, StageName ,Account_Name__c,Accouint_Last_Activity_Date__c
                                             From Opportunity 
                                             Where Accouint_Last_Activity_Date__c != THIS_FISCAL_QUARTER];
        
        User adminProfile = [Select Id From User Where Receive_TB_Grant_Emails_Notifications__c = TRUE];
        List<Id> listOfUserIds = new List<Id>();
        for(User usr : [Select Id From User Where ProfileId = :adminProfile.Id]) {
            listOfUserIds.add(usr.Id);
        }
        
        Test.startTest();

            String jobId = System.schedule('ScheduleApexClassTest',  CRON_EXP, new NoActivityThisQrtr());
            CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
            System.assertEquals(CRON_EXP, ct.CronExpression);
            System.assertEquals(0, ct.TimesTriggered);

        Test.stopTest();
    }
}

I have tried this test class and only got 17%
 
@istest
public with sharing class NoActivityThisQrtrTest {
    static testmethod void testSample() {
        Test.startTest();
        NoActivityThisQrtr obj = new NoActivityThisQrtr();
        obj.execute( null );
        Test.stopTest();
    }
}

 
Antoninus AugustusAntoninus Augustus
Hi Cyndie,
It’s best practice to keep your schedulable classes logic free. Schedulable classes are usually used alongside batch classes. These two classes would then be tested separately within the same test class, each would have their own test methods.

Here’s the documentation on best practices when using schedulable classes:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm

Here’s an example of how it would look like:
public class NoActivityThisQrtr implements Schedulable {
    public void execute(SchedulableContext sc) {
        NoActivityThisQrtrJob newJob = new NoActivityThisQrtrJob(); 
        Database.executebatch(newJob);
    }
}

You would then have all your logic within the batch class.