3

I am using platform events and in one of the after triggers I am calling a method in a class where the method is annotated with @Future(Callout=true)

In my test method below I am doing some DML to insert an account and opportunity record before I call Test.startTest(). My code is below, but I keep getting the "You have uncommitted work pending" error.

//insert dml here..

List<Job_Posting__e> jobPostingList = new List<Job_Posting__e>();

Job_Posting__e jobPosting = new Job_Posting__e();
jobPosting.jobTitle__c = 'Java Developer';
jobPosting.jobLocation__c = 'Raleigh, NC';
jobPostingList.add(jobPosting);

Test.startTest();

Test.setMock(HttpCalloutMock.class, new ServiceHttpResponseMock());

List<Database.SaveResult> results = EventBus.publish(jobPostingList);

Test.stopTest();

If I move the the line with EventBus.publish(jobPostingList) after Test.stopTest() the error goes away, but I think that line should be within the Test.start() and Test.stopTest() shouldn't it?

How can I resolve this error given the code above?

  • N.B. You can coerce platform event delivery before reaching Test.stopTest() by using Test.getEventBus().deliver() – cropredy Aug 11 at 3:48
4

Firstly, The async Apex will be executed only at point Test.stopTest(). So, when you are moving the EventBus.publish(jobPostingList) line after stopTest, it is never getting executed and so your future callout method will not even be covered in test.


Based on comment from @sfdcfox

I tested this again. It seems future callout from platform event trigger without stopTest is not executing but same future method from account trigger (after insert) is getting invoked without stopTest. (Have to do further testing for different types of objects). However this will not affect the current question in context - You need to check for DMLs in future method before callout.


Note that below test class will run without any problem:

@isTest
static void test(){
    Test.startTest();
    insert new Account(Name='test');
    Test.setMock(HttpCalloutMock.class, new AnimalsHttpCalloutMock());
    List<Database.SaveResult> results = EventBus.publish(new List<POC_Platform_Event__e>{new POC_Platform_Event__e()});
    Test.stopTest();
}

Although I have callout in Event trigger, above test method will be success. Thats because the actual callout is separated into separate transaction by using future.

However, the moment I introduce DML statement in future method before callout I get the uncommitted error. Below callout will give error:

@future(callout=true)
public static void mycallout(){
    insert new Account(Name='new test');
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
    request.setMethod('GET');
    HttpResponse response = http.send(request);
}

When I remove the line insert new Account(Name='new test');, the test class will be success again.

You need to check in your future method if there are DIRECT OR INDIRECT (through other class references/triggers) DMLs happening. There is no prob with your test class.

  • Async code run after test.stoptest is still run, FYI. The rest of the answer is fine, though. – sfdcfox Aug 10 at 13:56
  • Hi @sfdcfox. I just checked it again. I have future callout in platform event trigger (after insert). That is not even invoked without stopTest. Do you think something has changed in last 2 years? (salesforce.stackexchange.com/questions/173723/… was from May' 17) – salesforce-sas Aug 10 at 14:40
  • Strange, for platform event its not triggering without stoptest, but for account trigger its invoking. – salesforce-sas Aug 10 at 14:49
  • 1
    Yeah, in my answer, I stated it may be a bug. The test from then still fails. It may have something to do with Platform Events and how they "test." I did +1 your answer, though, just correcting the bit about asynchronous code not running after Test.stopTest(). There are situations where it does, and one should be aware of this feature. – sfdcfox Aug 10 at 15:21
  • Thanks!.. @sfdcfox.. Added that bit in answer – salesforce-sas Aug 10 at 17:15

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.