1

Scenario: Schedule send email to Users having System administrator profile about the closed opportunities for the month.

So I have created an apex scheduler for the above scenario and when I verified it manually, it is sending email as expected. Now I have created a test class but something seems to be wrong with it because after StopTest, email is not being sent. During assertion the expected value I think should be 1 but it is 0. I have also added few debug statements in which result is as expected.

Please help me out.

Below are the classes.

global class ClosedOppNotification implements Schedulable {
    public static String cronExp = '0 0 18 L * ?';
    
    global void execute(SchedulableContext sc) {
        List<Opportunity> closedWonOpportunities = [Select Id, Name From Opportunity Where StageName = 'Closed Won' AND CloseDate = THIS_MONTH];
        List<Opportunity> closedLostOpportunities = [Select Id, Name From Opportunity Where StageName = 'Closed Lost' AND CloseDate = THIS_MONTH];
        
        // Add users in a list toAddresses
        List<User> adminUsers = [Select Email From User Where Profile.Name = 'System Administrator'];
        List<String> toAddresses = new List<String>();
        for(User admin : adminUsers) {
            toAddresses.add(admin.Email);
        }
        
        // Set the SingleEmailMessage and send email
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(toAddresses);
        mail.setSubject('Closed Won and Closed Lost Opportunities for Last Month');
        if(closedWonOpportunities.isEmpty() && closedLostOpportunities.isEmpty()) {
            mail.setPlainTextBody('No Opportunity was closed this month.');
        }
        else {
            mail.setPlainTextBody('Closed Won Opportunities are:' + '\n' + closedWonOpportunities + '\n' + 
                             'Closed Lost Opportunities are:' + '\n' + closedLostOpportunities);
        }
        
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
    }
}
@isTest
private class ClosedOppNotificationTest {
    @isTest
    static void testClosedOpp() {
        Test.startTest();
        
        Opportunity opp1 = new Opportunity(Name='Opp1', StageName = 'Prospecting', CloseDate = System.today());
        insert opp1;
        opp1.StageName = 'Closed Won';
        update opp1;
        System.debug(opp1.CloseDate);
            
        List<Opportunity> closedWonOpportunities = [Select Id, Name From Opportunity Where StageName = 'Closed Won' AND CloseDate = THIS_MONTH];
        System.debug(closedWonOpportunities.size());
        System.debug(closedWonOpportunities[0].Name);
        
        // Schedule the test job
        String jobId = System.schedule('ClosedOpportunitiesNotification', ClosedOppNotification.cronExp, new ClosedOppNotification());
        System.debug(jobId);
        
        // Verify that there is no email sent before execution
        System.assertEquals(0, Limits.getEmailInvocations(), 'Email should not be sent.');
        
        CronTrigger ctBefore = [SELECT Id, CronExpression, TimesTriggered FROM CronTrigger WHERE id = :jobId];
        System.debug(ctBefore);
        System.assertEquals(0, ctBefore.TimesTriggered);
        
        Test.stopTest();
        
        CronTrigger ctAfter = [SELECT Id, CronExpression, TimesTriggered FROM CronTrigger WHERE id = :jobId];
        System.assertEquals(1, ctAfter.TimesTriggered);
        
        // Verify that an email is sent after execution of ClosedOppNotification
        System.assertEquals(1, Limits.getEmailInvocations(), 'An email should be sent.');
    }
}

1 Answer 1

1

Can you Move your email functionality to a method and then call that method from execute. This way your assertion will work. Scheduler Code

global with sharing class MySchedulable implements Schedulable {
global void execute(SchedulableContext SC) {
    sendEmail();
}

global void sendEmail() {
    List<User> adminUsers = [Select Email From User Where Profile.Name = 'System Administrator'];
    List<String> toAddresses = new List<String>();
    for(User admin : adminUsers) {
        toAddresses.add(admin.Email);
    }
    
    // Set the SingleEmailMessage and send email
    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    mail.setToAddresses(toAddresses);
    mail.setSubject('Just a Test Email');
    mail.setPlainTextBody('Hi From VS Else');
    
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}

}

Test class for scheduler

@isTest
public class MySchedulableTest {
@isTest static void test() {
    
    Test.startTest();
        MySchedulable thisInstance = new MySchedulable();
        /*String jobId = System.schedule('MySchedulerTest', '0 0 18 L * ?', new MySchedulable());
        System.debug(jobId);*/
        thisInstance.sendEmail();
        Integer invocation = Limits.getEmailInvocations();
    Test.stopTest();
    /*CronTrigger ct = [ SELECT TimesTriggered, NextFireTime
        FROM CronTrigger
        WHERE Id = :jobID
    ];
    System.assert(false, ct.TimesTriggered);*/
    
    // Verify that an email is sent after execution of ClosedOppNotification
    System.assertEquals(1, invocation, 'An email should be sent.');
}

}

As test class ensures SendEmail method is working fine.

2
  • Send email functionality is working fine that I had ensured manually. I removed the Scheduler part and then called the method from Execute Anonymous Window and it was working fine. I did get the email. The problem seems to be with Scheduler I guess because after Test.stopTest(), the async call for scheduler should run and email should be sent and Limits.getEmailInvocations() should return 1. But it is returning 0 which means email is not being sent which then means that scheduler class is not being executed properly. Jul 11, 2020 at 17:21
  • BTW, take a look at Apex access modifiers. Generally speaking there's no need to use "global" in your code. You only need it for cross-application code access (e.g. when a package wants to expose an API to third parties).
    – Phil W
    Jul 12, 2020 at 8:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .