An year ago I asked a question regarding the advantages of using testSetUp annotation instead of having a method for common data and calling it in every test method. My main issue at the time with using testSetup method was if it issues 30 queries, every test method starts its life with only 70 queried remaining and on top of that the data created in it is unavailable in test methods. We have to explicitly query again.

I happened to notice that if I wrap the whole testSetup code between Test.startTest() and Test.stopTest(), the soql queries are not counted against the individual test methods and we can use Test.startTest() and Test.stopTest() again in the test methods.

Question:

Since this behavior is not documented, are there any negative effects from this approach?

Example:

@isTest
private class AvinashTest {

    @testSetup static void commonData(){
        Test.startTest();

        Account a = (Account) TestFactory.createSObject(new Account(), true);
        Contact c = (Contact) TestFactory.createSObject(new Contact(), true);
        Opportunity o = (Opportunity) TestFactory.createSObject(new Opportunity(AccountId=a.Id,StageName='Closed Lost', Channel_Type__c = 'Direct'), true);
        Product2 prod1 = (Product2) TestFactory.createSObject(new Product2(), true);
        PricebookEntry pbe = (PricebookEntry) TestFactory.createSObject(new PricebookEntry(Product2Id = prod1.Id), true);
        Asset ast = (Asset) TestFactory.createSObject(new Asset( Product2Id = prod1.Id, AccountId = a.Id), true);

        System.Debug('**commonData**'+Limits.getQueries()); //Returns 16

        Test.stopTest();
    }

    @isTest static void demoMethodOne() {

        System.Debug('**demoMethodOne**'+Limits.getQueries()); //Returns 0

        Test.startTest();

        Opportunity o = [SELECT Id FROM Opportunity LIMIT 1];

        Test.stopTest();

    }

    @isTest static void demoMethodTwo() {

        System.Debug('**demoMethodTwo**'+Limits.getQueries()); //Returns 0

        Test.startTest();

        Opportunity o = [SELECT Id FROM Opportunity LIMIT 1];

        Test.stopTest();

    }

}
up vote 4 down vote accepted

This is a method you would have known about if you'd seen my previous answer on the subject. We use this internally because without using this technique, we continually run into governor limits on some of our larger tests. Several developers, including myself, have independently found this feature, and it's allowed us to continue building our internal applications without more aggressive optimization of our code. So far, we've observed no negative consequences from this technique, but have enjoyed more reliable tests and the ability to insert a lot more standardized test data than was previously possible.

  • Thank you. I used to avoid testSetup methods when there are large data sets since I need to query for every object again in test methods. – Avinash May 7 at 20:00
  • @Avinash Yes, I've created an idea for that. Even so, even if you have to query the records back, you still save on DML rows/statements and initial set up query rows/statements, so it's better than not using it at all. – sfdcfox May 7 at 20:02
  • I agree. At the time I didn't know about this behavior since it is not documented anywhere. I asked a question about pros and cons of the testSetup back in Feb 2017. Many developers shared their opinions...but no one discussed this approach. – Avinash May 7 at 20:05
  • If these methods are used with the only intent to create a new set of limits, shouldn't they be renamed to something more intuitive? Test.OpenLimitSet / Test.CloseLimitSet (or something like that)? – toadgeek May 7 at 23:17
  • @toadgeek Test.startTest is designed to give you the ability to simulate the start of a transaction (where you'd normally have no limits used), and Test.stopTest has several purposes, notably triggering asynchronous code to run synchronously. It just so happens that in testSetup is has the effect of resetting the governor limits for the tests themselves. I feel this technique should not be necessary; testSetup should automatically have its own set of limits, because it cripples the limits of the unit test. – sfdcfox May 7 at 23:24

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.