I have added some fields for Compliance to EmailMessage and Campaign objects. When a list email is sent, a batch job finds the tasks and copies those fields from the campaign related to the list email. Similarly the batch job copies those fields from EmailMessage as well. (Yes, I will have to make sure that part waits a little so that users have time to add Compliance information to the EmailMessage.)

The above functionality all works fine, and my Apex coverage test successfully proves that the list email tasks were updated as expected with Compliance information.

However, it seems to be impossible to write a coverage test to prove the single email task was updated correctly.

Inside of startTest() I use Messaging.sendEmail(), wait 10 seconds with a sleep function that does work, and then find the EmailMessage. Hopefully this should ensure that Salesforce's hidden flow that somewhere creates the Task actually runs. Instead, I find that EmailMessage.ActivityId is always null.

I found that Salesforce will not send email during tests in order to avoid spamming people. Though you can count invocations. Does this mean that it is impossible to actually find tasks created by sendEmail because they will never be created?

While I only lose a few lines of coverage, it is a problem that I cannot force the task creation flow to run.

Thanks for your help.


There are some things that are impossible to test in Salesforce. Things like field history and email tasks are generated during the "transaction finalization" step of a transaction, which occurs only after the transaction has run to completion and Salesforce is ready to permanently commit changes to the database.

As you've observed, this happens to be at the end of the unit test after everything else has happened in your test, except unit tests instead rollback everything except debug logs, so there's no way to actually observe the data created as a result of a unit test.

You can get the code coverage a few ways, such as the stub API, or extracting the logic to a separate method for testing purposes, but you won't be able to actually validate the logic.

  • Thank you very much. I ended up 1) moving the code out from the trigger to an invocable method called by a process created in Process Builder, and 2) adding faking logic to simulate operations for code coverage. Today though I found a post suggesting that setting EmailMessage.Sent to 3 (Sent) would create a linked Task. salesforce.stackexchange.com/questions/193030/… – skycafe Oct 3 '20 at 8:47

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.