The test method gets its set of governor limits, exclusive of the content between startTest and stopTest. I have faced the issue of 101 SOQL Governor Limits in test classes and mostly I have been able to resolve it by either using startTest/stopTest or by splitting into a new methods. We will have to set up test data in the beginning of the test method and then do the actual testing(logic, governor limits bulk testing, performance evaluation etc). But what will happen if we reach a situation where we hit the governor limits in a test method at the time of data setup itself.

Suppose I want to test some functionality of adding attachments to child products of opportunity. My business logic dictate that I do the following to create an opportunity product:

Data Model : Account > Contact > Opportunity > OpportunityProduct

  1. Create an account
  2. Create a contact under that account
  3. Create an opportunity under the contact
  4. Create a product under the opportunity
  5. Create an attachment under that product

Consider that the org is extensive and many custom functionalities exists for all these objects. So if there are 30 SOQL queries in the triggers for each of these objects - the test class will fail due to 101 SOQL even before reaching step 5.

I agree the situation I presented is pretty exaggerated - 30 queries for each object is pretty bad. But I hope I am making the picture clear, that in big projects, isn't there a possibility where we run into governor limits in test class just at the time of data creation.I am actually running into this already.

Please do share your thoughts.

  • 1
    I've been faced with this and the usual culprit is the lack of good trigger patterns, not actually using the trigger pattern correctly, concerns not being separated, classes refetching setup data that could be cached once per transaction and so on. I'm not saying this is your situation but sometimes, one has to bite the bullet and refactor logic to avoid this issue. I know I made myself unpleasant to some other team members who violated one or more of the above. – cropredy Feb 3 '16 at 1:25
up vote 3 down vote accepted

You may have to limit the number of records you create, even down to one per type. If it's still hitting the limit at that point, you're pretty much SOL. As a last resort, you can use SeeAllData=true so that you aren't hitting triggers. Test.loadData won't really help as it still fires triggers.

One solution you can implement as you build out your org (which may be more difficult to implement with existing functionality) is to build trigger stop flags into your handler pattern. My template looks something like:

public with sharing class LeadTriggerHandler
{
    @TestVisible static Boolean bypassTrigger = false;

    final List<Lead> newRecords;
    final Map<Id, Lead> oldMap;
    public LeadTriggerHandler(List<Lead> newRecords, Map<Id, Lead> oldMap)
    {
        this.newRecords = newRecords;
        this.oldMap = oldMap;
    }

    public void beforeInsert()
    {
        if (bypassTrigger) return;
        //LeadSerivices.method1(newRecords);
    }
    public void afterInsert()
    {
        if (bypassTrigger) return;
        //LeadSerivices.method2(newRecords);
    }

    public void beforeUpdate()
    {
        if (bypassTrigger) return;
        //LeadSerivices.method1(newRecords);
    }
    public void afterUpdate()
    {
        if (bypassTrigger) return;
        //LeadSerivices.method3(newRecords);
    }
}

Then in your test you can just do:

LeadTriggerHandler.bypassTrigger = true;
insert new Lead(/*data*/);
LeadTriggerHandler.bypassTrigger = false;

This flagging strategy can dramatically streamline your tests, and can be implemented in a variety of ways. The key is that the flag is static, though I think it is important to keep it private if at all possible.

  • This helps. I admire the framework logic - yes conditionally preventing some trigger parts from being executed if that is not the functionality we are testing seems to be an effective guard in this situation. But again in my situation, the functionalities are highly interrelated and multiple - misaligning one step in the trigger could possibly have unprecedented impact. I do like the idea! Thank you – Prajith Feb 2 '16 at 22:20
  • @Stygon Yes your situation sounds quite complicated. You could implement multiple flags as well if you need that level of control. For example you could include bypassBeforeInsert or even bypassMethod3. – Adrian Larson Feb 2 '16 at 22:21
  • Yes I agree. Eagerly waiting for the time salesforce provided a separate higher limit for data load in test class or ability for multiple startTest/stopTest in a test method. Optimism drives my current org ;) Thanks Adrian for the helpful suggestions. – Prajith Feb 2 '16 at 22:26
  • @AdrianLarson 'as a last resort, you could use SeeAllData=true ' - given that the test class requires a complex test setup, using seeallData=true is highly likely to introduce sandbox v prod issues when the testmethods run, now or in the future. :-). Your trigger guard pattern is useful though – cropredy Feb 3 '16 at 1:22

Your Answer

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.