[SalesForce] Exception: No body supplied for the file attachment.: [fileAttachments]

I have an Apex class that contains @future annotation method to send email. A Visualforce page is rendered as pdf and is sent as an email. I'm getting an exception in test class-

System.EmailException: SendEmail failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, No body supplied for the file attachment.: [fileAttachments]

Controller code(@future annotated)-

    PageReference pdf =  Page.ReceiptPrintPage;                       
        pdf.getParameters().put('AccId',parameter1); 
        pdf.getParameters().put('year',String.valueOf(parameter2));
        pdf.setRedirect(true);
        // Take the PDF content            
        Blob b;
      try{
            b = pdf.getContentAsPDF();
        }catch(Exception ex){
          System.debug('ex'+ex);
      }    

        // Create the email attachment
        String filename = parameter3 + '_receipt_' + parameter2 + '.pdf'; 
      Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
        //Messaging.EmailFileAttachment.setContentType(param1)                
        efa.setFileName(filename);
        efa.setBody(b);                               

        // Sets the paramaters of the email
        String subject = 'Recurring Donations Receipt for the Fiscal Year - ' + parameter2;                                                   
        body = 'Hello';
        email.setSubject(subject);
        email.setToAddresses(new String[] {parameter4});
        email.setPlainTextBody(body);           
      email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});                                             
        // Sends the email
        Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});

Test code-

    PageReference pdf =  Page.ReceiptPrintPage;
    pdf.getParameters().put('AccId',a1.Id); 
    pdf.getParameters().put('year',String.valueOf(fiscalYear));
    pdf.setRedirect(true);                
    Blob b;
    try{
        System.debug('before test content');      
        //b = pdf.getContentAsPDF();
        b = pdf.getContent();
    }catch(Exception ex){
        System.debug('ex'+ex);
    }  

    Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
    String filename = 'Receipt_' + fiscalYear + '.pdf';                                  
    efa.setFileName(filename);
    efa.setBody(b);                                   

    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    String body = 'Testing Email';
    String subject = 'Recurring Donations Receipt for the Fiscal Year - ' + fiscalYear; 

    email.setSubject(subject);
    email.setToAddresses(new String[] {'company@domain.com'});                
    email.setPlainTextBody(body);           
    email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});                                           
    Messaging.SendEmailResult[] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});              

How can I set body for file attachment?

Best Answer

Your code is correct.
The issue you are having is that pdf.getContent(); is throwing an exception and the Blob variable b is null by the time efa.setBody(b); is executed (because it was never initialised).

Edit with what I mean, including the suggestion of @Rahul Sharma/Bob ;)

If you put the logic outside, its easier to cover with a test, and then you just leave the send-message out. something like...

private /*or public*/ static Messaging.SingleEmailMessage getEmailMessage(String paramAccountId, String paramYear, String paramFilePrefix, String paramToAddress);
    PageReference pdf =  Page.ReceiptPrintPage;
    pdf.getParameters().put('AccId',paramAccountId);
    pdf.getParameters().put('year',paramYear);
    pdf.setRedirect(true);
    // Take the PDF content
    Blob b;
    try {
        if (Test.IsRunningTest()) {
            b = Blob.valueOf('My awesome pdf, but txt');
        } else {
            b = pdf.getContentAsPDF();
        }
    } catch(Exception ex){
        System.debug('ex'+ex);
        // actually do something about it, like sending an error message to an admin or opening a ticket or something
    }


    // Create the email attachment
    String filename = paramFilePrefix + '_receipt_' + paramYear + '.pdf';
    Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
    //Messaging.EmailFileAttachment.setContentType(param1)
    efa.setFileName(filename);
    efa.setBody(b);

    // Sets the paramaters of the email
    String subject = 'Recurring Donations Receipt for the Fiscal Year - ' + paramYear;
    body = 'Hello';
    email.setSubject(subject);
    email.setToAddresses(new String[] {paramToAddress});
    email.setPlainTextBody(body);
    email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

    return email;
}

Having in the @future method something like

Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {getEmailMessage(parameter1, String.valueOf(parameter2), parameter3, paramater4)});

and in the test method something like

Messaging.SingleEmailMessage toBeTested = getEmailMessage(parameter1, String.valueOf(parameter2), parameter3, paramater4);

System.assertEquals(new List<String>{parameter4}, toBeTested.getToAddresses());
System.assertNotEquals(null, toBeTested.getFileAttachments());
System.assertEquals('Recurring Donations Receipt for the Fiscal Year - ' + String.valueOf(parameter2), toBeTested.getSubject());
....
Related Topic