3

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?

2

From what I recall when they were announced at THDX17, platform events aren't sObjects that are supported by the queueable class at this time.

Also, the queuable won't execute until after Test.stop.Test() since it's an asynchronous operation. If Platform events are supported, the queueable will only execute AFTER Test.stopTest() occurs. You'll want to query the job id to see if it executed.

| improve this answer | |
  • Normally Queueable Apex is executed between the startTest and StopTest. But in this case the jobID of this code results into: null... – Wim Sep 8 '17 at 12:55
  • You've essentially moved it to an @future method when you enqueued it. You'll want to get the job Id from the trigger context, query to show that it hasn't executed, then query again for it after test.stopTest for it's status. – crmprogdev Sep 8 '17 at 12:59
1

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);
| improve this answer | |
0

Have you tested whether executing the same line:

Database.SaveResult results = EventBus.publish(new MessageEvent__e(Type__c ='TEST', Body__c='TEST'));

works in Execute Anonymous outside of a unit test scenario?

Sometimes in unit tests if one asynchronous job calls another, the latter won't finish. The one I've seen most often is, if a Schedulable calls a Batchable, then when you call the Schedulable in a unit test you'll never see the Batchable complete even if it was all called between Test.startTest() and Test.stopTest(). The Schedulable completes, the Batchable is added to the queue, and possibly the start() method executes but nothing else.

And remember, although Apex triggers are not normally asynchronous, they are for Platform Events, which means you do indeed have one async calling another.

| improve this answer | |
  • I have tried running it in Anonymous Apex, although then the Debug logs should show under a different User: "Automated Process". But that has the same results. – Wim Sep 8 '17 at 12:38
0

It seems that this feauture is indeed not yet possible in Salesforce, just like Call-Outs from a Platform Event Trigger.

If you want this feature, please vote on my idea on the Success Community: https://success.salesforce.com/ideaView?id=0873A000000lFK8QAM

| improve this answer | |
0

Perhaps this issue was resolved in Spring '18, but I believe System.enqueueJob works just fine in a platform event trigger. Below is a link to a repo showing sample code you can try out in a sandbox or scratch org.

https://github.com/martyychang/sfdx-platform-event-test

While the AsyncHelloEventTriggerTest.publishDefaultHello test will fail (something I've asked Salesforce Support to investigate), you can prove that in the live system the async job does get enqueued and executed as expected. Executing the anonymous Apex code below will result in a task being created.

EventBus.publish(
    new AsyncHelloEvent__e(TargetName__c = 'Anon'));
| improve this answer | |

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.