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
Joe HayesJoe Hayes 

Help with Test Class that sends email from a button on a Visualforce page

Hi Everyone,

I am having a biot of trouble creating a test class for my controller. What I have is only testing 18% of the code.

Please can someone take a look and see where I am going wrong?

Controller:
public class TrainingConfirmationSend {
    ApexPages.StandardController controller;   
 
 public course_sale__c q
 {get;set;}
    
 String op = ApexPages.currentPage().getParameters().get('id');
 
 public Id oppr   
 {get;set;}  

Public course_sale__c cf; 
 
 public TrainingConfirmationSend(ApexPages.StandardController ctrl)   
 {oppr = ctrl.getRecord().Id;}
     
 public void GetCustomFields() {
            cf = [SELECT id, Email_to_send_confirmation_to__c, courses__r.venue_address__c, courses__r.Course_Name__c, courses__r.Duration__c, courses__r.Course_Start_Date__c, courses__r.Start_Time__c, courses__r.Finish_Time__c, courses__r.Training_Tutor__r.Name FROM Course_Sale__c WHERE id = :oppr];
  }
 public PageReference emailAtt()
 {    
	EmailTemplate template = [SELECT Id, Subject, HtmlValue, Body FROM EmailTemplate WHERE Id = '00XD0000001dOXr'];
       
    GetCustomFields();
     
    String subject = template.Subject;
	subject = subject.replace('{!Courses__c.Course_Name__c}', cf.courses__r.Course_Name__c);
    
    String htmlBody = template.HtmlValue;
	htmlBody = htmlBody.replace('{!Courses__c.Course_Name__c}', cf.courses__r.Course_Name__c);
    htmlBody = htmlBody.replace('{!Courses__c.Duration__c}', cf.courses__r.Duration__c.format());
    htmlBody = htmlBody.replace('{!Courses__c.Course_Start_Date__c}', cf.courses__r.Course_Start_Date__c.format());
    htmlBody = htmlBody.replace('{!Courses__c.Start_Time__c}', cf.courses__r.Start_Time__c);
    htmlBody = htmlBody.replace('{!User.FirstName}', UserInfo.getFirstName());
    htmlBody = htmlBody.replace('{!Courses__c.Finish_Time__c}', cf.courses__r.finish_time__c);
    htmlBody = htmlBody.replace('{!Courses__c.Venue_Address__c}', cf.courses__r.venue_address__c);
    htmlBody = htmlBody.replace('{!Courses__c.Training_Tutor__c}', cf.courses__r.Training_Tutor__r.Name);
    
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
     List<String> toaddress = new List<String>();
     toaddress.add(string.valueof(cf.Email_to_send_confirmation_to__c));
        mail.settoaddresses(toaddress);
        mail.setReplyTo('trainingbookings@certsure.com');
        mail.setSenderDisplayName('Certsure Training');
        mail.setBccSender(false);
        mail.setUseSignature(false);
        mail.saveAsActivity = true;
        mail.setSubject(subject);
        mail.setHtmlBody(htmlBody);
        
      //Set email file attachments
        List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();
        for (Attachment a : [select Id, Name, Body, BodyLength from Attachment where ParentId = :oppr])
        {
     
     // Add to attachment file list
        Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
        efa.setFileName(a.Name);
        efa.setBody(a.Body);
        fileAttachments.add(efa);
        } 
     
     // for the T&C's
        Document doc = [select id, name, body, contenttype, developername, type from Document where id = '015D0000003rgYq'][0];
        Messaging.Emailfileattachment MyDocefa = new Messaging.Emailfileattachment();
        MyDocefa.setContentType(doc.contentType);
        MyDocefa.setFileName(doc.developerName+'.'+doc.type);
        MyDocefa.setBody(doc.Body);
        fileAttachments.add(MyDocefa);  
        mail.setFileAttachments(fileAttachments);

      //Send email
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
  
     //Log Completed Activity
        GetCustomFields();
        String userId = UserInfo.getUserId();
     	Task t=new Task();
     	t.Subject = 'Confirmation Sent';
     	t.Status = 'Completed';
        t.Type = 'Email';
     	t.ActivityDate = System.Today();
     	t.WhatId = cf.id;
     	t.Description = 'Confirmation Successfully Sent to '+cf.Email_to_send_confirmation_to__c;
        t.OwnerId = userid;
        t.Priority = 'Normal';
        insert t;       
        return null;
}
    
}

test class:
@istest
public class testTrainingConfirmationSend
{
  static testmethod void TrainingConfirmationSend()
  {
        Account acc=new Account();
        acc.Name = 'Test';
        insert acc;
        
        Courses__c crs=new Courses__c();
        crs.Name = 'Test';
        insert crs;
               
        Opportunity op=new Opportunity();
        op.RecordTypeId = '012D0000000kBZn';
        op.Name = 'Test';
        op.AccountId = acc.Id;
        op.Opportunity_Type_NICEIC_Training__c = 'In House Course';
        op.Customer_Type__c = 'New';
        op.StageName = 'Open';
        Date dt = Date.Today();
        op.CloseDate = dt;
        insert op;        
         
        Course_Sale__c cs=new Course_Sale__c();
        Decimal delnum = 4;
        cs.Delegates__c = delnum;
        cs.Opportunity__c = op.Id;
        cs.Email_to_send_confirmation_to__c = 'joehayes89@gmail.com';
        cs.Total_Revenue__c = delnum;
        cs.Courses__c = crs.Id;
        insert cs;        
        
        Attachment attach=new Attachment();    
        attach.Name='Test Attachment';
        Blob bodyBlob=Blob.valueOf('A Little Test From Joe');
        attach.body=bodyBlob;
        attach.parentId=cs.id;
        insert attach;
      
        Task t=new Task();
     	t.Subject = 'Confirmation Sent';
     	t.Status = 'Completed';
        t.Type = 'Email';
     	t.ActivityDate = System.Today();
     	t.WhatId = cs.id;
     	t.Description = 'Confirmation Successfully Sent to '+cs.Email_to_send_confirmation_to__c;
        String userId = UserInfo.getUserId();
        t.OwnerId = userid;
        t.Priority = 'Normal';
        insert t;
        
        List<Attachment> attachments=[select id, name from Attachment where parent.id=:cs.id];
        System.assertEquals(1, attachments.size());
        Task[] task = [select id, subject from task where whatId =:cs.Id];
        System.assertEquals('Confirmation Sent', task[0].subject);

      PageReference pageRef = Page.SendTrainingConfirmation;
      Test.setCurrentPage(pageRef);
      TrainingConfirmationSend con = new TrainingConfirmationSend(new ApexPages.StandardController(cs));	
      String nextPage = con.emailAtt().geturl();
      
  }
}

Thanks for your help. I can't work it out at all.


Thanks
Joe
Brenda S FinnBrenda S Finn
Joe

What line(s) are being covered by your unit test?

On line 64 in the controller, why are you querying for a Document with a hard-coded Id? Presumably, in unit test mode, you will not have visibility to a Document with that Id unless you turn on SeeAllData which is not best practices.

You also do the same for the Email Template on line 22 which seems dangerous.

Both these queries, querying based on SF Id, are not advised. The Id issued to the Email Template and Document will not be the same from our org to another so while you may get this to work in the SB, when you go to deploy it, your code will not work the same.

Also - be aware that emails are not sent when executing a Unit Test.

one more question - what happens when you run your unit test - are you getting any exceptions/errors? Your emailAtt() method returns null (which I know means display current page) but in unit test mode, it is still null so I would have thought that calling geturl() that would result in a NPE.
Joe HayesJoe Hayes
Hi Brenda,

Thanks for your help, I am fairly new to writing apex to be honest and have been thrown in at the deep end a little.
I didnt realise I shouldn't hard code id's. I guess if I selected from NAME 'Terms & Conditions.pdf' that might be better?

I dont really know how to write test classes, I've done a few that seem to cover enough code but it is trial and error to be honest.
My idea was to create records for the test and then run the controller from the test and verify the correct things had happened.

I guess my test class needs to make sure the attachments have been added, an email has been sent and a task has been logged.

Thanks for your time
Joe