[SalesForce] Queueable Apex not working in Platform Event Trigger

I am unable to use Queueable Apex in a Platform Event trigger but do not know why. I didn't found any documented limitations on this, so I am wondering if it is indeed possible.

This is my Queueable Apex class:

public class Test_QueueableClass implements Queueable
{
    public void execute(QueueableContext context)
    {
        System.debug('Hello World');
    }
}

This is my Platform Event Trigger:

trigger MessageEventTrigger on MessageEvent__e (after insert)
{
    System.debug('Trigger Context');
    Id jobId = System.enqueueJob(new Test_QueueableClass());
}

Unit Test:

@isTest
private class testTrigger
{
  static testMethod void runTest()
  {
    test.startTest();
    Database.SaveResult results = EventBus.publish(new MessageEvent__e(Type__c ='TEST', Body__c='TEST'));
    test.stopTest();
  }
}

All I see in the debug Log is the 'Trigger Context' message, but not the 'Hello World' message..

Any ideas?

Best Answer

After struggling with this for longer than I'd like to admit, I found a method that enables us to test Platform Event Triggers that enqueue Queueable jobs. The magical method is:

Test.getEventBus().deliver();

What you need to do is call Test.getEventBus().deliver() after you have called EventBus.publish(platformEvents). Just make sure you do this between Test.startTest() and Test.stopTest()

The gotcha is that YOU MUST call Test.getEventBus().deliver() before Test.stopTest()

Here's some code to illustrate:

Test.startTest();

// Publish a platform event that will enqueue a `Queueable` job
EventBus.publish(new Some_Platform_Event__e(Foo__c = 'bar'));

// Deliver the platform event RIGHT NOW
Test.getEventBus().deliver();

// Let's see what happened
List<AsyncApexJob> asyncApexJobs = [
    SELECT Id, Status
    FROM AsyncApexJob
    WHERE JobType = 'Queueable'
];

// We have 1 Queueable job that has been Queued
System.assertEquals(1, asyncApexJobs.size());
System.assertEquals('Queued', asyncApexJobs[0].Status);

Test.stopTest();

// Now let's see what happened after stopping the test
asyncApexJobs = [
    SELECT Id, Status
    FROM AsyncApexJob
    WHERE JobType = 'Queueable'
    AND Id = :asyncApexJobs[0].Id
];

// The Queueable has completed!
System.assertEquals('Completed', asyncApexJobs[0].Status);
Related Topic