How to test that Apex Batch finish() sends an email?

Batches don't run until stopTest(), and stopTest() restores the test method's limits after the batch executes before it returns. This means that your test method will never see that limit set unless it sends an email itself (which, of course, will never be delivered/sent).

You have two ways to handle this:

  1. Don't bother with the assert. Assuming the email isn't sent, an exception is thrown; if you don't catch the exception in finish, the exception will be thrown out to the test method, and if you don't have a try-catch block, the entire test automatically fails anyways, which is the point of your assert call, right?

  2. Set a static @TestVisible method in your MyBatch class. On the last line of finish, set that value to Limits.getEmailInvocations(). Once you come back from the batch, you can examine this value.


global class MyBatch ... {
    @TestVisible static Integer emailLimits;
    global void finish(...) {
        ...
        MyBatch.emailLimits = Limits.getEmailInvocations();
   }
}

Just a bit lengthy process, but you will be able to test that. At the start of the test create the custom setting with any value and name.

Now need to create additional class say EmaiHandler class which implement the Messaging.InboundEmailHandler interface.

global class EmailServiceHandler implements Messaging.InboundEmailHandler 
{
        global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email,Messaging.InboundEnvelope envelope) 
        {
    if (email.plainTextBody== 'Sample Email')
           {
              // some logic to update the custom setting u have created
           } 
           Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
           return result;
 }
}

Now u need to configure your email setting in the org and need to check out the email id that the salesforce org will listen.Refer to below link to do the same.

http://wiki.developerforce.com/page/An_Introduction_To_Email_Services_on_Force.com

Now after wards in the test class at the start of the test initialize the custom setting with some dummy value.

before calling the batch pass the emailid(eg. [email protected]) that the salesforce will listen and the body string that u have mentioned in the handler class.

Now execute the batch .

if(customSetting__c.value =='Set in Handler Class') { It means the email is transmitted; put assert statements; }

This completes your testing for the same.