4

I have opportunity code that calls a future method. While testing it, I have run into some odd behaviour. I cannot get my assertion to fail if it occurs after the stopTest() call. In fact, it seems that no code (even assertions) is being executed after the stopTest() call.

After troubleshooting and debugging, I have boiled my test method down to this (note that the opportunity and contact are static class members):

public static testMethod void checkIntegrationUpdates()
{
    Test.startTest();
    opportunity.StageName = 'Closed Won';
    opportunity.OnBoarding_Type__c = 'Test Type'
    opportunity.Primary_Contact__c = contact.Id;
    Database.Saveresult updateResult = Database.update (opportunity);
    System.debug('Update Result: ' + updateResult.isSuccess());
    Test.stopTest();
    System.assertEquals(1,2);
}

If I move the assertion to before the stopTest() call, then the assertion correctly fails. If I move it to the line after the stopTest() call, as above, the assertion does not get called and the test passes.

Why does the assertion after the stopTest() call not get called? Isn't the correct way to test future methods to make all your assertions after the stopTest() call?

  • Is it printing out the debug? If not the update may be causing an exception? – techtrekker Nov 19 '12 at 22:45
  • Yes, it's printing out the debug. I can move the assertion to immediately after the debug and the test will fail as expected. – Paddyslacker Nov 19 '12 at 22:47
  • 1
    This is due to the future method calling a web service. Testing via the Salesforce UI causes the test to be skipped. Testing via Eclipse causes the test to fail silently. See Andrew's answer for a workaround using the new Winter 13 mocking capabilities. – Paddyslacker Nov 19 '12 at 23:57
2

Current Thoughts..

Ok after trying to spend some time reproducing what I suspect now might be a platform bug. I've got the following ideas for you to try, but nothing concreate.

  • If you comment out the cal to your future method in the trigger does it work?
  • If so, add it back in and remove gradually some parts of your future method
  • Run your code interactively, does the Apex Job UI show any failures in the future method?
  • Try to move code from your static initialisation into the scope of the test method if you can, I've known statics setup in tests cause some interesting side effects. Including if you can other static initialisers from other classes. The order of these is so dependent on the class loader I often try to avoid them.
  • If all else fails you appear to have a very good repo for a Salesforce Support case... :(

Update:

Since it appears that making Web Service callouts from Future methods in test situations causes this kind of silent failure. You might want to checkout this new feature in Winter'13, http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex_testing.htm

Reproduction Attempts

This works for me (not to keen on statics in tests tbh, but relfected what I assume you have in yours below). I suspect its an exception in your future call, are you doing this in a trigger?

static Opportunity opportunity;

static
{
    opportunity = new Opportunity();
    opportunity.Name = 'Test';
    opportunity.StageName = 'Closed Won';
    opportunity.CloseDate = System.today();
    insert   opportunity;           
}

public static testMethod void checkIntegrationUpdates()
{
    Test.startTest();
    opportunity.StageName = 'Closed Won';
    //opportunity.OnBoarding_Type__c = 'Test Type'
    //opportunity.Primary_Contact__c = contact.Id;
    Database.Saveresult updateResult = Database.update (opportunity);
    System.debug('Update Result: ' + updateResult.isSuccess());
    Test.stopTest();
    System.assertEquals(1,2);
}

Gives me...

enter image description here

By adding this...

@Future
public static void doSomethingInTheFuture()
{
    throw new FutureException('Stop in the future!');
}

public class FutureException extends Exception
{

}

And this...

trigger FutureOpp on Opportunity (before update) {
 TestTest.doSomethingInTheFuture();
}

And then this..

enter image description here

Which as you say should work, I wondering it its throwing an uncatchable exception?

  • Yes, it's from a trigger. The purpose of the test is to test the future call, so I want to test that after the future call, a custom field on the opportunity has been updated. As I could never get that to fail, I replaced the test for the updated field with the test for one not equalling two. – Paddyslacker Nov 19 '12 at 22:59
  • Ok I've added this to my test and my future exception is seen in the test. I wonder if your getting some kind of gack or uncatchable exception in your future call? If you do it interactively do you see any failure in the Apex Jobs UI? – Andrew Fawcett Nov 19 '12 at 23:01
  • Nope its not uncatchable exceptions, added Messaging.reserveMassEmailCapacity(5000); to the future method (which emits an unhandleable exception) and the test still sees it. – Andrew Fawcett Nov 19 '12 at 23:04
  • I was just about to update the thread to say that the future jobs complete successfully when I update the opportunity interactively. – Paddyslacker Nov 19 '12 at 23:09
  • Well, I'm all out for the mo, I've put a few suggestions in my answer, keen to see how this one pans out... I smell a platform bug personally...there is likely some multiple threading semantics going on behind the scenes here, you might have tripped into some corner case perhaps... – Andrew Fawcett Nov 19 '12 at 23:14

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.