[SalesForce] Automated testing of chained Queueable jobs in Salesforce

I am currently writing a queueable class for asynchronous processing in my triggers since triggers do not allow callouts. I am going achieve it by calling a class which implements the queueable interface.
When reading the documentation I found out that you can have 50 queueable in one transaction but can call only one queueable from a queueable class.

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_queueing_jobs.htm

Also, I can not chain the queueable jobs in apex test.
Salesforce documentation for chaining queueables in apex tests

Example of working class / method:
Below class will work in its own transaction.

EventTriggerHandler.afterInsert(){
  Boolean bDoACallout = isCalloutNecessary();
  if(bDoACallout){
    System.enqueueJob(new EventTriggerHandlerCallout((Map<Id, Event>)Trigger.newMap));
   }
  Boolean bSecondCondition = isSecondConditionTrue();
  if(bSecondCondition){
    System.enqueueJob(new Trial1Queueable((Map<Id, Event>)Trigger.newMap));
   }
  Boolean bThirdCondition = isThirdConditionTrue();
  if(bThirdCondition){
    System.enqueueJob(new Trial2Queueable((Map<Id, Event>)Trigger.newMap));
  } 
}

Now, Salesforce documentation says, above mentioned code will work but wont be testable and I need to wrap it around Test.isRunningTest() and I may be wrong but what I understood from that is, these queueables needs to be tested separately and not in the test of EventTriggerHandler itself.

EventTriggerHandler.afterInsert(){
  Boolean bDoACallout = isCalloutNecessary();
  if(bDoACallout){
    System.enqueueJob(new EventTriggerHandlerCallout((Map<Id, Event>)Trigger.newMap));
   }
  Boolean bSecondCondition = isSecondConditionTrue();
  if(bSecondCondition){
    System.enqueueJob(new Trial1Queueable((Map<Id, Event>)Trigger.newMap));
   }
  Boolean bThirdCondition = isThirdConditionTrue();
  if(bThirdCondition){
    System.enqueueJob(new Trial2Queueable((Map<Id, Event>)Trigger.newMap));
  } 
}

This was working on its own as expected all the unit tests were working too per my understanding of queueable class and apex tests. Above code will not work when Event is being created from a queueable itself. We did a clean up exercise to consolidate all the logic in one queueable class.
But, I am not sure how to code a smoke test / automated tests so that we catch these beforehand without manual tests of entire org.

Best Answer

When you need more than one execution, but you want to test the asynchronous code independently, you can cheat by rolling them back. Here's an example in a unit test:

Test.startTest();
SavePoint sp = Database.setSavePoint();

// Replace this with real code
executeTheTrigger();

// Do any asserts, etc...

// Roll back the transaction
Database.rollback(sp);
Test.stopTest();

Then, you can get a natural 100% coverage of your trigger code without this error. Note that you should prefer to do any assertions before you roll back the state, since any modifications will disappear. Also remember you'll need to unit test your Queueables independently.

Related Topic