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
Dev AlwaysDev Always 

test class error. email body missing field required

I wrote an apex class which works fine. However, the test class keeps failing with the error: System.EmailException: SendEmail failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Email body is required.: [] Not sure what I am doing wrong. Can you please help? I have attached my code and test class below

global class XYZLetter {   
    global static void sendLetter(List<String> recordId) {
        
//Get Files from ContentDocumentLink Object
    List<ContentDocumentLink> cdls = [select Id,ContentDocumentId,ContentDocument.Title,LinkedEntity.Name From ContentDocumentLink where LinkedEntityId=:recordId AND ContentDocument.Title LIKE 'xyz%'];
    
    Set<Id> contentDocumentIds = new Set<Id>();
    for (ContentDocumentLink cdl : cdls) {
        contentDocumentIds.add(cdl.ContentDocumentId);
    }   
        
    List<Id> attachmentIds = new List<Id>();    
//Get all related contentVersion file     
    List<ContentVersion> documents = ([SELECT Id FROM ContentVersion WHERE isLatest = true AND ContentDocumentId IN :contentDocumentIds]);
    for (ContentVersion doc : documents) {
        attachmentIds.add(doc.Id);
    }
    
//Get details on the Application    
   Card__c pcard = [SELECT Id,Letter_Failed__c, RecordTypeId FROM Card__c WHERE Id=:recordId];
   
    String cardholderContactId=pcard.Card_Applicant__c;

//-********************
 
    if(attachmentIds.size()==0){
        EmailTemplate NoXYZ = [SELECT id FROM EmailTemplate WHERE developerName = 'Letter_Not_Found'];
        
        OrgWideEmailAddress[] owea = [select Id from OrgWideEmailAddress where Address = 'oxyxSF@COMPANY.COM'];
        String[] ccAddresses = new String[] {'cardinquiries@company.com'};
        
        //Apex Single email message
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        if ( owea.size() > 0 ) {
            mail.setOrgWideEmailAddressId(owea.get(0).Id);
        }    
      
        mail.setTemplateID(NoXYZ.id);//templateID
        mail.setTargetObjectId(cardholderContactId);// contact Id of cardholder
        mail.setCcAddresses(ccAddresses);
        //No attachment found here, so no need to try and attach mail.setEntityAttachments(attachmentIds);
        mail.setWhatId(pcard.Id);  
        Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMessage> {mail};
        Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);
            if (results[0].success) {
                System.debug('The email for XYZ Letter not found was sent successfully.');
            } else {
                System.debug('The email for XYZ Letter not found failed to send: '+ results[0].errors[0].message);
                 pcard.XYZ_Letter_Failed__c = true;
             }
     
              Update pcard;
   }//end if attachmentIds.size()==0 (Send 'XYZ Letter Not Found' Template end)
//-********************

//-********************
   //Otherwise, end message as expected
    else {
        Id pcardRTypeId = [SELECT Id FROM RecordType WHERE sObjectType='Card__c' AND developerName ='PCard_Approval'].Id;
        Id finRTypeId = [SELECT Id FROM RecordType WHERE sObjectType='Card__c' AND developerName ='Information_Updates'].Id;

        EmailTemplate pcardET = [SELECT id FROM EmailTemplate WHERE developerName = 'X3_Approved'];
        EmailTemplate finET = [SELECT id FROM EmailTemplate WHERE developerName = 'X20_Information_Update_Approved'];
        EmailTemplate SingleFinET = [SELECT id FROM EmailTemplate WHERE developerName = 'X201_Single_Information_Update_Approved'];
        EmailTemplate MonthlyFinET = [SELECT id FROM EmailTemplate WHERE developerName = 'X202_Monthly_Information_Update_Approved'];
        
        String et;
        if (pcard.RecordTypeId == pcardRTypeId){
            et = pcardET.Id;
        }
        else if (pcard.RecordTypeId == finRTypeId){
            //et = finET.Id;
            if (pcard.Monthly_Purchase_Card_Update__c && pcard.Single_Purchase_Card_Update__c){
                et = finET.Id;
            }
            else if(pcard.Monthly_Purchase_Card_Update__c){
                et = MonthlyfinET.Id;
            }
            else if(pcard.Single_Purchase_Card_Update__c){
                et = SingleFinET.Id;
            }
        }

       
        

        OrgWideEmailAddress[] owea = [select Id from OrgWideEmailAddress where Address = 'XYZsalesforce@COMPANY.COM'];
  
        String[] ccAddresses = new String[] {'p-cardinquiries@COMPANY.COM'};
      
        if (pcard.PCard_Supervisor__c != null){
           ccAddresses.add(pcard.PCard_Supervisor__c);
        }
        if (pcard.Approving_Official_Lookup__c != null){
           ccAddresses.add(pcard.Approving_Official_Lookup__c);
        }
        
        List<String> idList = new List<String>();
        Group g = [SELECT (select userOrGroupId from groupMembers) FROM group WHERE NAME =:pcard.CPublic_Group__c];
        for (GroupMember gm : g.groupMembers) {
            idList.add(gm.userOrGroupId);
        }
        
        User[] usr = [SELECT email FROM user WHERE id IN :idList];
        for(User u : usr) {
            ccAddresses.add(u.Id);
        }
  
    //Apex Single email message
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        if ( owea.size() > 0 ) {
            mail.setOrgWideEmailAddressId(owea.get(0).Id);
        }    

    mail.setTemplateID(et);//templateID
    mail.setTargetObjectId(cardholderContactId);// contact Id of cardholder
    mail.setCcAddresses(ccAddresses);
    mail.setEntityAttachments(attachmentIds);
    mail.setWhatId(pcard.Id);  // card recordId
        
    Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMessage> {mail};
    Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);
        if (results[0].success) {
           System.debug('The email was sent successfully.');
        } else {
           System.debug('The email failed to send: '+ results[0].errors[0].message);
        }

        
    }

Here is the test class:
@isTest
public class DPALetterTest {
    static testMethod void sendEmailwithAttachment() {
        Test.startTest();
        
        EmailTemplate et = [SELECT id FROM EmailTemplate WHERE developerName = 'X3_PCard_Approved'];
        Id pcardRTypeId = [SELECT Id FROM RecordType WHERE sObjectType='PCard__c' AND developerName ='PCard_Approval'].Id;
        Id finRTypeId = [SELECT Id FROM RecordType WHERE sObjectType='Purchase_Card__c' AND developerName ='Information_Updates'].Id;
       // String pcardRTypeId = recTypeId.Id;
        
        Account acc = new Account();
        acc.Name='ABCTest';
        insert acc;

        String profileName1 = 'Card Application User';
        
        User admin = [SELECT Id, Username, UserRoleId FROM User WHERE Profile.Name = 'System Administrator' AND UserRole.Name='XYZSystem Admin' LIMIT 1];
       
        System.runAs(admin){

            User u1 = new User(
                ProfileId = ([SELECT Id FROM Profile WHERE Name=:profileName1].Id),
                LastName = 'user1',
                Email = 'test.user1@test.com',
                Username = 'test.ccpuser1@test.com',
                CompanyName = 'XYZ',            
                Alias = 'alias',          
                TimeZoneSidKey = 'America/Los_Angeles',
                EmailEncodingKey = 'UTF-8',
                LanguageLocaleKey = 'en_US',
                LocaleSidKey = 'en_US'             
            );
            insert u1;

            User u2 = new User(
                ProfileId = ([SELECT Id FROM Profile WHERE Name=:profileName1].Id),
                LastName = 'user2',
                Email = 'test.user2@test.com',
                Username = 'test.ccpuser2@test.com',
                CompanyName = 'CBER',            
                Alias = 'alias',          
                TimeZoneSidKey = 'America/Los_Angeles',
                EmailEncodingKey = 'UTF-8',
                LanguageLocaleKey = 'en_US',
                LocaleSidKey = 'en_US'             
            );
            insert u2;

         Group gp = [SELECT ID FROM Group WHERE Name='PCard XYZ CCP Group'];   
        GroupMember gpm = new GroupMember();
        gpm.GroupId = gp.Id;
        gpm.UserOrGroupId = u1.Id;            
        Database.insert(gpm);

        Contact applicant1 = new Contact(firstName='test', lastName = 'applicant11',accountId=acc.id, email ='test.applicant11@abctest.com');
        insert applicant1;
        Contact supervisor1 = new Contact(firstName='test', lastName = 'supervisor12',accountId=acc.id, email ='test.supervisor12@abctest.com');
        insert supervisor1;  
        Contact ao1 = new Contact(firstName='test', lastName = 'ao11',accountId=acc.id, email ='test.ao11@abctest.com');
        insert ao1;              
        
        Card__c app1 = new Card__c(); 
        
        app1.RecordTypeId = pcardRTypeId;
        app1.Cardholder_Name__c  = 'Test Applicant11';
        app1.Cardholder_Email_Address__c='Test.Applicant11@abctest.com';
        app1.PCard_Applicant__c = applicant1.Id;
        app1.PCard_Supervisor__c = supervisor1.Id;
        app1.Approving_Official_Lookup__c = ao1.Id;      
        insert app1; 
            
        Purchase_Card__c app2 = new Purchase_Card__c(); 
        
        app2.RecordTypeId = finRTypeId;
        app2.Cardholder_Name__c  = 'Test Applicant11';
        app2.Cardholder_Email_Address__c='Test.Applicant11@abctest.com';
        app2.Card_Applicant__c = applicant1.Id;
        app2.Card_Supervisor__c = supervisor1.Id;
        app2.Approving_Official_Lookup__c = ao1.Id;
        insert app2; 
   
          
            // Insert Salesforce Files using Apex Class:
         //Create Document
        ContentVersion cv = new ContentVersion();
        cv.Title = 'XYZ Test Document';
        cv.PathOnClient = 'TestDocument.pdf';
        cv.VersionData = Blob.valueOf('Test Content');
        cv.IsMajorVersion = true;
        Insert cv;
                            
             //Get Content Documents
    Id conDocId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:cv.Id].ContentDocumentId;
 
    //Create ContentDocumentLink 
    ContentDocumentLink cdl = New ContentDocumentLink();
    cdl.LinkedEntityId = app1.Id;
    cdl.ContentDocumentId = conDocId;
    cdl.shareType = 'V';
    cdl.Visibility = 'AllUsers';
    Insert cdl; 
            
    ContentDocumentLink cdl2 = New ContentDocumentLink();
    cdl2.LinkedEntityId = app2.Id;
    cdl2.ContentDocumentId = conDocId;
    cdl2.shareType = 'V';
    cdl2.Visibility = 'AllUsers';
    Insert cdl2; 
                       
        
         Integer emailbefore = Limits.getEmailInvocations();

         List<String> recordIds=new List<String>{app1.Id};  
         List<String> finRecordIds=new List<String>{app2.Id};  
         XYZLetter.sendLettXYZer(recordIds);   
         XYZLetter.sendXYZLetter(finRecordIds);    
  
        system.assertNotEquals(emailbefore,Limits.getEmailInvocations(),'should have decreased');
        Test.stopTest();         
        
    }
}

}
Shri RajShri Raj
The error message suggests that there is no email body, and hence, the email sending failed. Looking at your code, it seems that you are only setting the email template ID and email recipient, but not setting the email body. To resolve this error, you need to set the email body.
You can set the email body either by specifying the plain text message body using setPlainTextBody() method or by specifying the HTML message body using setHtmlBody() method of the Messaging.SingleEmailMessage class.
Here's an example code snippet:
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setTemplateID(template.Id);
mail.setTargetObjectId(recipientId);
mail.setCcAddresses(ccAddresses);
mail.setPlainTextBody('This is the email body.');
Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{ mail });

You can replace the setPlainTextBody() method with setHtmlBody() method if you want to send an HTML-formatted email.