If I send an email via Apex

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

How can I create a unit test and test whether it was sent? Checking e.g. Limits.getEmailInvocations() doesn't actually work, because the emails are not sent out for real during tests. Or should I simpy assume that it works for the given contact and emailtemplate?

  • 1
    FYI - I have several tests that use limits.getEmailInvocations and they pass successfully and seem to be incremented during tests. SO if you need to test an email was sent like during an error condition that is caught, you can use this to test it was sent
    – Eric
    Commented Oct 27, 2017 at 2:23

2 Answers 2


Testing emails involves many things

  1. To test that the properties of an email are properly set and that your code actually tries to send an email, see this Stackexchange answer that exploits ApexMocks.
  2. To test that an email template is properly rendered before sending it, the savepoint - rollback hack is no longer required. You can use built-in Apex methods that render an email template. These are described in this stackexchange answer

The latter use case will mean you should create a wrapper method around your rendering of the template so you can unit test that method in a testmethod by passing in different arguments and verifying the proper application of merge fields to the template

For example

public Messaging.SingleEmailMessage render(ID templateId, ID whoId, ID whatId) {
 return Messaging.renderStoredEmailTemplate(templateId, whoId, whatId);

and the testmethod

// Given Sobjects corresponding to the whoId and whatId. Mock or fetch an email template and note the Id

Account a = new Account(...);
insert a;
Contact c = new Contact(...);
insert c;
EmailTemplate et;

System.runAs([select Id from User where Id = :Userinfo.getUserId() limit 1][0]) {       // creating setup objects requires diff context
  Folder[] folders = [select Id from Folder 
                        where AccessType IN: new list<String>{'Shared','Public'} 
                          AND Type = 'Email'];
  System.assert(!folders.isEmpty(),'test can\'t run wo Email Template folders. Folders can\'t be mocked in Apex');

  //    Given an EmailTemplate with merge fields
  et = new EmailTemplate(   Name = 'TestEmailTemplate ApexTestMethod',
                            Body = someBodyWithMergeFields, 
                            DeveloperName = 'TestEmailTemplate_ApexTestMethod', 
                            FolderId = folders[0].Id,
                            HtmlValue =someBodyWithMergeFields,
                            IsActive = true,
                            TemplateType = 'custom');
  insert et;            

// When rendering...
Messaging.SingleEmailMessage res = new myClass().render(et.Id, c.id, a.Id);

// Then verify rendered template


Note that you can't use mocked SObjects in memory here to test the above because the code under test actually queries the database given the Ids passed.


As Messaging.sendEmail() is Salesforce build in functionality, there's no need to test it. The only thing you can test is setting email up. I guess you should be able to attempt to send an email, then rollback it like:

Savepoint sp = Database.setSavepoint();
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {tempMail});

and verify if the tempMail is filled with the correct data.

  • I'm only not sure if you can use savepoint and rollback in test methods, but I can't see any reason why it shouldn't. Please let me know if it work as it should. Commented Oct 15, 2015 at 8:55
  • We want to test the email templates to see if they merge correctly and throw no errors for several contacts. I'll try and see if this works and check the HTMLbody of mail for content. I'm thinking I already tried that and it didn't work, but let me check again :-) Commented Oct 15, 2015 at 8:58
  • It is important to ask yourself if it is possible that the code would stop working because of some changes in the future. If so, then that's a good idea to create unit test for this. If no, then I would make some initial manual testing. Commented Oct 15, 2015 at 9:08
  • 1
    @willemMulder - The rollback technique is no longer required. See Apex methods renderEmailTemplate and renderStoredEmailTemplate: developer.salesforce.com/docs/atlas.en-us.apexcode.meta/…
    – cropredy
    Commented Oct 24, 2017 at 22:17
  • @cropredy correct! I'm already using that in many projects. If you want to add it as an answer, I'll gladly accept that one. Commented Oct 26, 2017 at 8:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .