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
snapssnaps 

Help writing a test class for sending emails

I have a class designed to send an email from an opportunity.  Opportunities have a lookup to an object called the Panel Tool and there is a junction object called "panelists" that links the panel tool to contacts. I am pulling the contacts' emails via the soql query, and then adding them to the list of emails so that users do not have to manually type in email addresses.

 

Now, I'm working on my first ever Apex test class, and am running into some difficulties. Here is the code I need to test on:

 

public class sendEmail {

    public String subject { get; set; }
    public String body { get; set; }
    private final Opportunity opportunity;

    /*
     * Creates a constructor that populates the Opportunity object with the nominator's name and email address.
     * The nominator's email should never be blank - otherwise, his contact information would not show up.
     */
    public sendEmail() {
        opportunity = [SELECT Name, 
            (SELECT Engagement_Role__c.Name, Engagement_Role__c.Contact__r.Email, Engagement_Role__c.Contact__r.FirstName 
            FROM Opportunity.R00NR0000000UWbWMAW WHERE Role__c='Nominator' AND Engagement_Role__c.Contact__r.Email != NULL ) 
            FROM Opportunity WHERE Id = :ApexPages.currentPage().getParameters().get('id')];
    }

    public Opportunity getOpportunity() {
        return opportunity;
    }

    public PageReference send() {
        // Define the email
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); 

        String addresses;
        
        // Checks to see if there even exists a contact and email address before looping 
        // through the whole list of contacts and emails 
        if (opportunity.R00NR0000000UWbWMAW[0].Contact__r.Email != null) {
            addresses = opportunity.R00NR0000000UWbWMAW[0].Contact__r.Email;
            
            for (Integer i = 1; i < opportunity.R00NR0000000UWbWMAW__r.size(); i++) {
                if (opportunity.R00NR0000000UWbWMAW[i].Contact__r.Email != null) {          
                    addresses += ':' + opportunity.R00NR0000000UWbWMAW[i].Contact__r.Email;
                }
            }
        }

        String[] toAddresses = addresses.split(':', 0);

        // Sets the parameters of the email
        email.setSubject( subject );
        email.setToAddresses( toAddresses );
        email.setPlainTextBody( body );
        
        // Sends the email
        Messaging.SendEmailResult[] resultMail = Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });

        // Redirects page to confirm that email was successfully sent
        PageReference sentTrue = new PageReference('/apex/emailSentTrue?Id=' + opportunity.id); 
        sentTrue.setRedirect(true); 
        return sentTrue;
    }
}

 

 And here is the partial test code that I have written:

 

@isTest

private class testSendEmail {
    private static testMethod void testSend() {
        
        sendEmail controller = new sendEmail();
        Opportunity[] opp = [SELECT Name, 
            (SELECT Engagement_Role__c.Name, Engagement_Role__c.Contact__r.Email, Engagement_Role__c.Contact__r.FirstName 
            FROM Opportunity.R00NR0000000UWbWMAW WHERE Role__c='Nominator' AND Engagement_Role__c.Contact__r.Email != NULL ) 
            FROM Opportunity WHERE Id = '0064000000BKcY9'];
        Opportunity newOpp = opp[0];
        insert newOpp;
        String nextPage = controller.send().getUrl();
        
        test.startTest();
        PageReference page = controller.send();
        test.stopTest();
        
        System.assertEquals('Alberto', newOpp.name);
        System.assertEquals('/apex/sendEmailPage?Id=0064000000BKcY9', nextPage);
        
        }
}

 

I realize my testing is incomplete and that I haven't tested all conditions yet. My problem however is that my code never reaches beyond the here:

 

    public sendEmail() {
        opportunity = [SELECT Name, 

 

What exactly am I doing wrong here?

sfdcfoxsfdcfox
1) You shouldn't be querying against a hard-coded ID. Use only the opportunity you've manually inserted.

2) newOpp is missing required fields. It won't insert into the database, thus your test will fail.

3) Since you're asking for a page parameter, you need to specify that parameter, such as ApexPages.currentPage().getParameters().put('id',newOpp.Id), before attempting to construct the controller (before new sendEmail()).

#3 is why your code is failing, but #1 and #2 will be important later.
snapssnaps

Thank you for your quick response. I tried #3, and it doesn't appear to make a difference. I've also been struggling to figure out how to manually insert the opportunity for awhilenow - how exactly would you do that? 

sfdcfoxsfdcfox

Example:

 

public class ConstructorWithPageParam{
  	public Id recordId;
    public ConstructorWithPageParam() {
		recordId = ApexPages.currentPage().getParameters().get('id');
    }
}

 

@isTest
class ConstructorWithPageParamTest{
    @isTest static void test() {
        ConstructorWithPageParam cwp = new ConstructorWithPageParam();
        System.assertEquals(null,cwp.recordId);
        Opportunity newOpportunity = new Opportunity(Name='test',CloseDate=Date.Today(),StageName='test');
        insert newOpportunity;
        ApexPages.currentPage().getParameters().put('id',newOpportunity.Id);
        cwp = new ConstructorWithPageParam();
        System.assertEquals(newOpportunity.Id,cwp.recordId);
    }
}

 

snapssnaps

Okay, I tried this:

 

public sendEmail() {
    recordId = ApexPages.currentPage().getParameters().get('id');
    opportunity = [SELECT Name, 
            (SELECT Engagement_Role__c.Name, Engagement_Role__c.Contact__r.Email, Engagement_Role__c.Contact__r.FirstName 
            FROM Opportunity.R00NR0000000UWbWMAW WHERE Role__c='Nominator' AND Engagement_Role__c.Contact__r.Email != NULL ) 
            FROM Opportunity WHERE Id = :recordId];
    }

 

as well as the test sample you provided, but I'm still getting the same amount of coverage as before. If I take out 

WHERE Id = :recordId

 

then I get the error "System.LimitException: Too many query rows: 50001."