0

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();
    }
}

1 Answer 1

1

It's strange that your first test method isn't gaining any coverage. The testmethod keyword is deprecated (you should be using the @isTest annotation instead), but it should still work.

You should be getting some coverage, since you are correctly calling System.schedule() inside of Test.startTest() and Test.stopTest() (and async code like queueable, batch, future, and scheduled is run after Test.stopTest().

Even though it's right, I'd suggest simply calling the execute() method directly as you are doing in your second attempt. You're not trying to test that Salesforce's scheduler mechanism is working (it's not something you can control, and you should trust that Salesforce is testing it themselves), you're trying to test whether or not your code is behaving correctly.

As for why you're not getting much coverage either way, that comes down to the fact that you're not creating test data. With the exception of "setup objects" like Users and Profiles (and a handful of other things), there is no data available in a test method unless you create it yourself. This is part of Salesforce's "test isolation", which is a good thing. It ensures that data you insert/update/delete as part of a test doesn't affect your actual data, and helps ensure that your tests pass in your sandbox as well as in production.

In your first attempt, List<Opportunity> listOfnoactivityOps = [query here] returns no data. You'll need to, at the very least:

  • create a new Account
  • insert it
  • create a new Opportunity
  • relate it to the test Account
  • insert the Opportunity

You'll also need to make sure that whatever feeds the Account_Last_Activity_Date__c field is set so that it is at least 3 months in the past (so you're not in the current quarter), otherwise the query in NoActivityThisQrtr isn't going to return any records.

You'll also want to make some assertions to verify that the work your class (the class being tested) is supposed to do has actually been done. Limits.getEmailInvocations() should help you there (you're expecting to send an email).

1
  • I've never been able to get Limits.getEmailInvocations() to work for me in testmethods but it has been a while so maybe things have changed. Best way I've seen to assert email contents is to use UnitOfWork pattern in fflib registerEmail
    – cropredy
    Jun 23 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.