Test Apex Publish Callbacks

To test your Apex publish callback class, add an Apex test class. You must provide Apex tests before you can package or deploy an Apex class to production and meet code coverage requirements.

In an Apex test, event messages are published synchronously in the test event bus. To simulate the execution of the callback methods in a test, you can deliver or fail the publishing of the event messages.

To simulate a failed publishing of an event or a batch of events, call this method.

1Test.getEventBus().fail();

The Test.getEventBus().fail() method causes the publishing of events to fail immediately after the call, and event messages are removed from the test event bus. This method causes the onFailure() method in the callback class to be invoked. When the event messages fail to publish, none of the triggers defined on the platform event receive any failed events.

To simulate successful event delivery, call the Test.getEventBus().deliver(); method or have your events delivered after Test.stopTest(). Event messages are delivered immediately after each of those statements. Successful event delivery triggers the execution of the onSuccess() method in the callback class.

Example: MyCallbackTest Test Class

This example class is a test class for the FailureAndSuccessCallback class given previously. This test class shows how to test the successful and failed publishing of test event messages in the test event bus. Before you run this test class, define a platform event in Setup with the label Order Event and a Text(18) field of Order Id.

1@isTest
2public class MyCallbackTest {
3    @isTest static void testFailedEventsWithFail() {
4        
5        // Publish with callback
6        FailureAndSuccessCallback cb = new FailureAndSuccessCallback();
7
8        // Create test event with EventUuid field value
9        Order_Event__e event = (Order_Event__e)Order_Event__e.sObjectType.newSObject(
10            null, true);
11        event.Order_Id__c='100';
12        System.debug('EventUuid of created event: ' + event.EventUuid);
13        // Publish an event with callback
14        EventBus.publish(event, cb);
15
16        // Fail event 
17        // (invoke onFailure and DO NOT deliver event to subscribers)
18        Test.getEventBus().fail(); 
19        
20        // Verify that tasks were created by the onFailure() method
21        List<Task> tasksFailed = 
22            [SELECT Id,Subject,Description FROM Task 
23             WHERE Subject='Follow up on event publishing failures.'];
24        System.Assert.areEqual(1,tasksFailed.size(),
25                            'Unexpected number of tasks received for failed publishing');
26        System.debug('tasksFailed[0].Description=' + tasksFailed[0].Description);
27        System.debug('event.EventUuid=' + event.EventUuid);
28        System.Assert.isTrue(tasksFailed[0].Description.contains(event.EventUuid),
29                            'EventUuid was not found in the Description field.');
30
31    }
32
33    @isTest static void testSuccessfulEventsWithDeliver() {
34        
35        // Publish with callback
36        FailureAndSuccessCallback cb = new FailureAndSuccessCallback();
37
38        // Create test event with EventUuid field value
39        Order_Event__e event = (Order_Event__e)Order_Event__e.sObjectType.newSObject(
40            null, true);
41        event.Order_Id__c='99';
42        // Publish an event with callback
43        EventBus.publish(event, cb);
44        
45        // Deliver events published so far
46        // (invokes onSuccess and delivers events to subscribers)
47        Test.getEventBus().deliver();
48        
49        // Verify that tasks were created by the onSuccess() method
50        List<Task> tasksSuccessful = 
51            [SELECT Id,Subject,Description FROM Task 
52             WHERE Subject='Follow up on successful event publishing.'];
53        System.Assert.areEqual(1,tasksSuccessful.size(),
54                            'Unexpected number of tasks received for successful publishing');
55        System.Assert.isTrue(tasksSuccessful[0].Description.contains(event.EventUuid),
56                            'EventUuid was not found in the Description field.');
57    
58    }
59
60    @isTest static void testSuccessfulEventsWithStopTest() {
61        
62        // Start test
63        Test.startTest();
64        
65        // Publish with callback
66        FailureAndSuccessCallback cb = new FailureAndSuccessCallback();
67
68        // Create test event with EventUuid field value
69        Order_Event__e event = (Order_Event__e)Order_Event__e.sObjectType.newSObject(
70            null, true);
71        event.Order_Id__c='99';
72        // Publish an event with callback
73        EventBus.publish(event, cb);
74        
75        // After the test ends, it delivers the events published 
76        // (invokes onSuccess and delivers to subscribers)
77        Test.stopTest();
78        
79        // Verify that we have two tasks created by the onSuccess() method:
80        // one task from the earlier deliver() call and one event after Test.stopTest()
81        List<Task> tasksSuccessful = 
82            [SELECT Id,Subject,Description FROM Task 
83             WHERE Subject='Follow up on successful event publishing.'];
84        System.Assert.areEqual(1,tasksSuccessful.size(),
85                            'Unexpected number of tasks received for successful publishing');
86        System.Assert.isTrue(tasksSuccessful[0].Description.contains(event.EventUuid),
87                             'EventUuid was not found in the Description field.');
88    }
89}

Example: MyCallbackTestWithCorrelation Test Class

This example class is a test class for the FailureCallbackWithCorrelation class given previously. This test class shows how to test the failed publishing of test event messages in the test event bus. The callback retries publishing events for a maximum of two attempts so the test fails the publishing of a test event twice in a loop. It verifies that, each time, the callback retries publishing the event by checking that the retryCounter variable has been increased. Before you run this test class, define a platform event in Setup with the label Order Event and a Text(18) field of Order Id.

1@isTest
2public class MyCallbackTestWithCorrelation {
3   
4    @isTest
5    static void testFailedEventsWithFail() {
6        // Create test event
7        Order_Event__e event = (Order_Event__e)Order_Event__e.sObjectType.newSObject(
8            null, true);
9        event.Order_Id__c='dummyOrderId';
10        
11        // Populate map
12        Map<String,String> uuidMap = new Map<String,String>();
13        uuidMap.put(event.EventUuid, 'dummyOrderId');
14        
15        // Create callback
16        FailureCallbackWithCorrelation cb = new FailureCallbackWithCorrelation(uuidMap);
17        
18        // Make sure retry counter is 0
19        Assert.areEqual(0, cb.getRetryCounter(), 
20            'Newly created callback should have retry counter at 0');
21        
22        // Publish an event with callback
23        EventBus.publish(event, cb);
24		
25        // If we fail all publish attempts, callback should run MAX_RETRIES times. 
26        // For each attempt, the callback should republish the event, 
27        //    increase the counter, and update the map
28        String prevUuid = event.EventUuid;
29        for (Integer i = 1; i <= FailureCallbackWithCorrelation.MAX_RETRIES; i++) {
30            Test.getEventBus().fail();
31            Assert.areEqual(i, cb.getRetryCounter(), 'Retry counter should be ' + i);
32            Assert.areEqual(1, cb.getUuidMap().size(), 'Map size should be 1');
33            String currUuid = (new List<String>(cb.getUuidMap().keySet())).get(0);
34            Assert.areNotEqual(prevUuid, currUuid, 
35                'Map should be updated with newly created event Uuid');
36            Assert.areEqual('dummyOrderId', cb.getUuidMap().get(currUuid), 
37                'Map value should be the original Order Id');
38            prevUuid = currUuid;
39        }
40        
41        // If we publish another failed event, callback should not retry.
42        Order_Event__e event2 = (Order_Event__e)Order_Event__e.sObjectType.newSObject(
43            null, true);
44        event2.Order_Id__c='dummyOrderId';
45        EventBus.publish(event, cb);
46        Test.getEventBus().fail();
47        Assert.areEqual(FailureCallbackWithCorrelation.MAX_RETRIES, cb.getRetryCounter(), 
48                        'Retry counter should still be ' +
49                         FailureCallbackWithCorrelation.MAX_RETRIES);
50    }
51}