I am about to roll out some code which uses Platform Events
, and hitting a troublesome roadblock in testing. Is calling Test.stopTest()
supposed to cause subscriber triggers to fire and subsequently process published events?
No matter what I try, I cannot seem to get the subscriber triggers to fire in a test context. That leads to 0% coverage on the trigger body, which in turn means the trigger cannot be deployed.
The documentation states:
Usage
Each test method is allowed to call this method only once. Any code that executes after the stopTest method is assigned the original limits that were in effect before startTest was called. All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously.
The pub/sub logic seems asynchronous. Conclusion: trigger should fire!
The Platform Event Developer Guide
also touches on testing (emphasis mine):
Ensure that your platform event trigger is working properly by adding an Apex test. Before you can package or deploy any Apex code (including triggers) to production, your Apex code must have tests. To publish platform events in an Apex test, enclose the publish statements within
Test.startTest()
andTest.stopTest()
statements.Call the publish method within the
Test.startTest()
andTest.stopTest()
statements. In test context, the publish method enqueues the publish operation. The Test.stopTest() statement causes the event publishing to be carried out. Include your validations after the Test.stopTest() statement.// Create test events Test.startTest(); // Publish test events Test.stopTest(); // Perform validation here
Conclusion: trigger should fire!
However, the behavior I observe is that the subscriber trigger never fires, even after calling Test.stopTest()
. Here is the basic structure I am trying to test:
Trigger
trigger MyEvent on MyEvent__e (after insert)
{
MySubscriber.doStuff(trigger.new); // not covered
}
Subscriber
public with sharing class MySubscriber
{
public static void doStuff(List<MyEvent__e> events)
{
// implementation
// not covered
}
}
Test
static testmethod void testMySubscriberTrigger()
{
List<MyEvent__e> events = new List<MyEvent__e>
{
new MyEvent__e(/*data*/)
};
Test.startTest();
EventBus.publish(events);
Test.stopTest();
// make assertions
}
However, I get 0% coverage on my subscriber trigger, and none of the subscriber implementation gets covered either. Is the documentation wrong in this regard? How can I cover the trigger itself?
Every class and trigger involved is set to API Version 40.0.
I tried using plain old insert instead of publishing:
// instead of:
// EventBus.publish(events);
// I tried:
insert events;
But I got this error:
System.DmlException: Argument must be of internal SObject type.
I also tried throwing an exception in the trigger to prove if it runs or not:
trigger MyEvent on MyEvent__e (after insert)
{
throw new DmlException('This trigger is running');
}
However, the test passed without any exception encountered.
I have so far tested this functionality on CS14
and raised a case on this issue today (#16685012).