Where is the error in the unit test for a Platform Event trigger that updates another record

platform-eventtriggerunit-test

Context: I mostly work declaratively but can hack together a little Apex when needed.

I am using Platform Events to change the user context to Automated Process to facilitate a post to Chatter not possible by the user publishing the event (B2BMA Integration user).

A Platform Event 'New Pardot Task' is created with a single custom field containing the Id, as a string, of the Task I wish to reference. There is one trigger on the platform event that finds and updates the Task custom checkbox field 'Create Chatter Post' to 'true'. This can then kick off a Flow/PB to post to chatter as the Automated Process user. In any event, the trigger works exactly as intended but I'm struggling with the test class.

The assertion fails and shows t.Create_Chatter_Post__c is still 'false' even though I have experienced it working correctly. I'm wondering if there's something about the context in which the test is run that's causing the assertion failure when the actual feature is working as expected. I think it might have to do with the 'Publish After Commit' setting on Platform Event—possibly this means it's technically an asynchronous transaction (?)—but I'm not sure how to modify my test class to handle that.

Edit: Using Execute Anonymous to confirm the trigger is working correctly WILL update the checkbox (visible in the UI) although the debugger shows it as false – which furthers my suspicion that it's a problem with the asynchronous nature of platform events.

Trigger

trigger NewPardotTaskTrigger on New_Pardot_Task__e (after insert) {
    // list of Tasks to hold for update and bulkify trigger
    List<Task> tasks = new List<Task>();
    for (New_Pardot_Task__e event : Trigger.New){
        // Update Task as Automated Process User
        // Using custom checkbox to make updates declarative via Flow
        Task t = [SELECT id FROM Task WHERE id =: event.Record_Id__c];
        t.Create_Chatter_Post__c = true;
        tasks.add(t);
    }
    update tasks;
}

Test class
Edit: I have updated this to include re-querying the Task per Jesse's suggestion (still not working)

@isTest
public class NewPardotTaskTest {
    @isTest static void test1() {
        // Create task
        Task t = new Task(
            Subject = 'TEST1');
        insert t;
        New_Pardot_Task__e pardottask = new New_Pardot_Task__e(
            Record_Id__c = t.Id);
        // Create test event instance
        Test.startTest();
        // Call method to publish events
        Database.SaveResult sr = EventBus.publish(pardottask);
        Test.stopTest();
        // Check that the task that the trigger updated has Create Chatter Post selected
        t = [SELECT Create_Chatter_Post__c FROM Task WHERE Id = :t.Id];
        System.assertEquals(true, t.Create_Chatter_Post__c, 'Expected Create Chatter Post to be true');
    }
}

Execute Anonymous

New_Pardot_Task__e pt = new New_Pardot_Task__e(
Record_Id__c = '00T0300000A3kZiEAJ');
Database.SaveResult sr = EventBus.publish(pt);
if (sr.isSuccess()) {
    Task t = [SELECT Create_Chatter_Post__c FROM Task WHERE Id = '00T0300000A3kZiEAJ'];
    System.debug('Chatter post value: ' + t.Create_Chatter_Post__c);
} else {
    for(Database.Error err : sr.getErrors()) {
        System.debug('Error returned: ' +
                     err.getStatusCode() +
                     ' - ' +
                     err.getMessage());
    }
}

Best Answer

In this case, it appears that your test context isn't recognizing the update because you haven't "refreshed" the state of the task record. I believe the solution will be to re-query the task before asserting the value of Create_Chatter_Post__c, i.e.:

Code edited by OP for best final solution: - Removed EventBus.publish(pardottask) entirely as the creation of the platform event is already taken care of by a separate piece of automation, and this duplicity was creating a 'duplicate id in list' error

@isTest
public class NewPardotTaskTest {
    @isTest static void test1() {
        // Create task
        Test.startTest();
        Task t = new Task(
            Subject = 'TEST');
        insert t;        
        Test.stopTest();
        // Check that the task that the trigger updated has Create Chatter Post selected
        t = [SELECT Create_Chatter_Post__c FROM Task WHERE Id = :t.Id];
        System.assertEquals(true, t.Create_Chatter_Post__c, 'Expected Create Chatter Post to be true');
    }
}