10

Ok, this is going to become a quite long question. The main goal is to document strange platform behavior and maybe learn more why this happens.

It all started with that test which failed because setup code called an @future method which failed. (BTW: I was really confused to learn that @future are called at all without a Test.stopTest() which led to this question.)

Fails

@isTest
private class TestSetupTest1 {

    @isTest
    private static void willFail() {

        // Setup
        callFailingFutureMethod();

        // Verify 
        ...
    }
}

More or less by accident I made it work moving the setup code into a @TestSetup method:

Succeeds

@isTest
private class TestSetupTest2 {

    @TestSetup
    private static void setup() {
        callFailingFutureMethod();
    }


    @isTest
    private static void wontFail() {
        // Verify 
        ...
    }
}

It seems like the @future is not called at all or in a separate execution context here. That is my assumption because by adding Test.stopTest() here I can make it fail again.

Again fails

@isTest
private class TestSetupTest3 {

    @TestSetup
    private static void setup() {
        Test.startTest();
           callFailingFutureMethod();
        Test.stopTest();
    }


    @isTest
    private static void willAlsoFail() {
        // Verify 
        ...
    }
}
  • Is this question the same as this one? salesforce.stackexchange.com/questions/173723/… - The answer there seems to cover this but I may be missing the subtle differences? – Eric May 10 '17 at 13:31
  • No it's not. As I noted the are connected but the previous question is solved but this (my original problem is still open). – Robert Sösemann May 10 '17 at 13:34
  • The purpose of TestSetup is to generate the data for testing. I agree that its not documented that we should not call future method from TestSetup but same is true for many other things as well(future and batch foe example). Considering that it seems bad idea to call future methods from setup as you can not guaranty the execution start time. – AtulRajguru9 May 11 '17 at 4:32
  • 1
    We've seen some behavioral regressions with future methods in unit tests in the Spring '16 release. We have some business logic that runs async simply to get access to the higher governor limits offered. When we've tested those prior to Spring '16, the future method has been given those higher limits. Starting with Spring '16 that no longer occurs, so those tests started failing with "Too many SOQL queries" errors. This happens even when running as 38.0. Salesforce has acknowledged this issue and has scheduled a fix for Spring '17. Not sure if the root cause is the same, but perhaps related? – Scott Wells May 11 '17 at 14:04
5

Your setup definitely can run future methods, so they are not ignored entirely. This test passes for me on cs14 using any API Version between 35 and 40:

@IsTest
public class DemoFuture
{
    @TestSetup
    static void setupData()
    {
        createSomeData();
    }
    @future
    public static void createSomeData()
    {
        SObjectFactory.create(Account.sObjectType);
    }
    static testmethod void testFutureCall()
    {
        system.assertEquals(1, [SELECT count() FROM Account], 'Future should be run');
    }
}

If I change the body of the createSomeData() method to system.assert(false), the test fails. So future calls in @TestSetup are definitely respected at least some of the time.

| improve this answer | |
  • Maybe its a time dependent issue. The future method in our tests does a lot and the error stems from another complex issue: inserting setup and non setup objects. Otherwise there would be no difference between TestSetupTest2 and TestSetupTest3. – Robert Sösemann May 10 '17 at 13:31

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.