+ Start a Discussion
ncramerncramer 

Governor limits on @future methods in UI vs test methods

We are using the future annotation to raise governor limits for Apex Managed Sharing recalculations on object updates.  This works well when doing live testing through the UI, but after writing test methods, it appears that the testing routine does not apply the appropriate increase to the governor limit for soql queries that takes place in the 'live' environment when using the UI.  See below for two snippets of the debug log placed inside the future annotated method.  The first shows the number of queries avaialable when the original trigger is part of a test routine, the second when the same trigger is fired 'for real'.

---

Test class debug results:

20090223145031.385:Class.ManagedSharing.queueRecalcProperty: line 14, column 9: Passing through the future annotated method, 0 of 20 queries used.

...

Eventual error:

20090223145155.055:Class.ManagedSharing.recalcEsrEvent: line 349, column 70: returning from end of method public static void addRegionClientGroups(MAP:Id,Id, MAP:Id,Id) in 17 ms
System.Exception: Too many SOQL queries: 21

---

UI debug results:

20090223145235.009:Class.ManagedSharing.queueRecalcProperty: line 14, column 9: Passing through the future annotated method, 0 of 100 queries used.

Evenual successs:
Status Success
Vijay RautVijay Raut

Hi,

 

I am also facing same problem. We were having our app working fine till Friday (02/20) and then we had noticed this problem. Not sure. Have you got any response?

 

Thanks in Advance !!

V.R.

Message Edited by Vijay Raut on 02-23-2009 11:11 AM
ncramerncramer

At this point I have not received a response.  Is there a process for formally reporting possible defects?  Could someone point me to it?
 
Thanks,
nc 
jlojlo

ncramer,

 

You didn't include any of your code, so it's hard to say exactly where the problem is. Does your code use startTest() and stopTest()? 

 

Here's some sample code that I derived from this blog post: http://blogs.salesforce.com/support/2009/01/allowing-custom.html

 

 

public class GovernorTestClass {
@future
public static void updateUserInTheFuture(String userId) {
User u = [select Email,FirstName,LastName,Title
from User
where Id=:userId];

if (u!=null) {
// do something
}
}

static testMethod void testUpdateUserInTheFuture() {
User u = [select Id from User limit 1];

Test.startTest();
GovernorTestClass.updateUserInTheFuture(u.Id);
Test.stopTest();

}
}

 

Here's the interesting portion of the debug log:

 


*** Beginning Test 1: JTMP.GovernorTestClass.static testMethod void updateUserInTheFuture()

20090225161325.078:Class.JTMP.GovernorTestClass.updateUserInTheFuture: line 14, column 18: SOQL query with 1 row finished in 36 ms
20090225161325.078:Class.JTMP.GovernorTestClass.updateUserInTheFuture: line 17, column 9:     Changing testing limits to WebService context based on user-defined method invocation
Message Edited by jlo on 02-25-2009 09:18 AM
ncramerncramer


Snippets of code are below. The problem seems to be with running it through the test rather than actual execution.

If you add the Limits.getLimitQueries() inside the future method (and the future method gets called as part of a trigger), my experience is the testMethod call still has a limit of 20, while actually triggering the object in the UI appropriately raises the limit to 100.

 

Future method: 

    @future    Public static void queueRecalcProperty(Set<Id> propertyIds) {        system.debug('Passing through the future annotated method, ' +             Limits.getQueries() + ' of ' + Limits.getLimitQueries() +             ' queries used.');        recalcProperty(propertyIds); }    Public static void recalcProperty(Set<Id> propertyIds) {        // set up the property map with regions, clients included        Map<Id, Property__c> propertyMap = new Map<Id, Property__c>(           [select id, Region__c, Client__c                from Property__c               where id in :propertyIds]);                              recalcProperty(propertyMap); 

 

Trigger:

 trigger PropertyShareTrigger on Property__c (after insert, after update) {

		System.debug('Property objects in trigger: ' + Trigger.new.Size());	    Set<Id> propertyIds = new Set<Id>();    Set<Id> trigLookupChanged = new Set<Id>();            for (Integer i = 0; i < Trigger.new.size(); i++) {	                // figure out if a lookup has changed        if(Trigger.isUpdate)            if(Trigger.old[i].Region__c != Trigger.new[i].Region__c ||               Trigger.old[i].Client__c != Trigger.new[i].Client__c)                    trigLookupChanged.add(Trigger.new[i].id);    	// add changed objects to the map        if(Trigger.isInsert || trigLookupChanged.contains(Trigger.new[i].id))            propertyIds.add(Trigger.new[i].id);    }    // run the sharing update routines    if(propertyIds.size() == 1 && Trigger.isInsert)        ManagedSharing.recalcProperty(propertyIds);        else if(!propertyIds.isEmpty())        ManagedSharing.queueRecalcProperty(propertyIds);}

 

Test Method: 

 

    static testMethod void testPropertySingleUpdateTrigger() {        setupTestEnvironment();                Test.startTest();            System.debug('Updating single Property');            testProperty1.Region__c = testRegion2.Id;            testProperty1.Client__c = testClient2.Id;            update testProperty1;        Test.stopTest();
Message Edited by ncramer on 02-25-2009 09:21 AM
 Is there any easy way to get the code insert to retain my carriage returns using C&P? 
Message Edited by ncramer on 02-25-2009 09:22 AM
KumarSahabKumarSahab

Hi,

Future attonation call can not be applied on Triggers.

ncramerncramer

If you look at the limits debug line in my first post, a trigger can indeed call a future annotated method and receive the benefits of higher governor limits.  It is only in the test methods that higher limits are not granted.

 

nc 

Always ThinkinAlways Thinkin
Have to agree that this is a real problem and forces me to dumb down my test methods. I've batched and bulkified as much as I can, used a web service to get around limits before async was available and even coded in DML statement counters to break out of the execution before hitting limits. When I took my 83% test and tried to improve it, the expansion caused it to hit the non-async limits and fail, in my case on DMLs going over 20 instead of the 100 async limit.
TehNrdTehNrd

I'm a little late to the party on this one but if salesforce.com encourages, aka forces us to write unit tests, they need to give us the framework to support this.

 

Here is an idea as I didn't see one. Please go vote for it.

 

http://ideas.salesforce.com/article/show/10097033/future_asynchrounous_unit_test_must_reset_governor_limits