1

I have a bizarre issue. I have a trigger that will send an email based upon a record update. When I debug my trigger running the test class it showing the email result as success and when I debug and Limits.getEmailInvocations() it is correctly showing 1 right after calling sendEmails.

System.debug(Limits.getEmailInvocations()); // Debugs 0
Messaging.sendEmail(mails);
System.debug(Limits.getEmailInvocations()); // Debugs 1

When running my test method the assertion will fail however:

Test.startTest();
update recordsToUpdate;
Test.stopTest();
// This fails
System.assertEquals(1, Limits.getEmailInvocations());

I can even see the email activity being created in the log, so not sure why Limits.getEmailInvocations() is asserting wrong.

3

The reason is because the test.starttest and test.stoptest create a new apex context. Inside the context it will show 1.

so try:

Test.startTest();
update recordsToUpdate;
System.assertEquals(1, Limits.getEmailInvocations()); // Will show 1
Test.stopTest();
System.assertEquals(1, Limits.getEmailInvocations()); // Will fail as no invocations are visible

Edit

New info says that the email is being sent via a future method.

This will definitely cause the first assert above to fail as the future method is not called until test.stopTest(). I could see this causing the second assert to fail as well as future methods are called in separate contexts so the second assert would still not know if the email was sent.

One option would be to make sure emails are being saved as activities and to query for the activity. Then you can assert that the activity exists and you'll know your email will be sent.

Another would be to change your service class a little bit:

public static void sendEmail(String Message) {
    // All the email stuff
}

// Call non future method from future context
@Future
public static void sendEmailFuture(String message) {
    sendEmail(messsage);
}

Then in your test class you can test a few things:

@isTest
public static void sendEmailTest() {
    Service.sendEmail('Message'); // Call non future method
    System.assertEquals(1, Limits.getEmailInvocations()); // verify email
}

@isTest
public static void sendEmailFutureTest() {
    Test.startTest();
    sendEmailFuture('Message');
    Test.stopTest();

    system.assertEquals(1, Limits.getFutureCalls()); // Verify the future method was fired
}

This pattern is more versatile and can be used for other, non email tests where querying for the activity may not be an option.

  • Still fails for some reason. – Andrew L. Mar 6 '19 at 16:46
  • 3
    If emails are not sent in test context, am not sure Limits.getEmailInvocations() will ever return value. – Pranay Jaiswal Mar 6 '19 at 16:46
  • @AndrewL. What Pranay said. If it is still showing 0, that means that your trigger is not actually sending an email. You may need to debug your code. – gNerb Mar 6 '19 at 17:36
  • 2
    @gNerb The last line should compare to 0 to demonstrate that it passes. – sfdcfox Mar 6 '19 at 17:38
  • I think the problem may be is that the trigger is calling a future method. The future method is being called and tested in the test class and it debugs the correct values, but maybe the test context is incorrect. Not sure really. – Andrew L. Mar 6 '19 at 18:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.