10

Can you clarify how Test.startTest() and Test.stopTest() work? I would have thought the limits in the code below would have produced 1 soql query, and instead I'm seeing 100.

Code:

public static testmethod void test123(){
    for (integer i = 0; i < 99; i++){
        List <account> accts = [select name from Account];
    }
    Test.startTest();
    List <account> accts = [select name from Account];
    system.debug('made it here');
    Test.stopTest();
    system.debug('done');
}

Debug Logs

00:37:18.486 (5486903866)|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 100 out of 100 ******* CLOSE TO LIMIT
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

00:37:18.486 (5486903866)|TESTING_LIMITS
00:37:18.486 (5486903866)|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 0 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Maximum CPU time: 0 out of 10000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 100
  Number of Email Invocations: 0 out of 10
  Number of future calls: 0 out of 50
  Number of queueable jobs added to the queue: 0 out of 50
  Number of Mobile Apex push calls: 0 out of 10

3 Answers 3

5

When you run a unit test, Test.startTest() "sets aside" the testing governor limits, and creates a new set of limits based on the next line of execution. For example, if the next line of code is a DML operation, it sets up a normal trigger execution governor limit, while if it's a Database.exectuteBatch method, it sets the governor limits to the Batchable limits instead.

So, you should definitely see two sets of limits, the former for the queries run outside of Test.startTest() and Test.stopTest(), and those inside. It's possible that since you didn't actually "do" anything inside the actual test phase, you may have caused some sort of bug, but ordinarily, you'd expect to see 99 "outside" queries and 1 "inside" query.

Calling Test.startTest() doesn't "wipe out" the other limits, it only temporarily suspends them.

10

I run the same code in the developer console and here is my debug log:

enter image description here

Here i'm seeing two different no. of soql queries.It is giving me the expected results.Not sure why it is not producing correct results in your case.

EDIT1:

After OP's comment i tested on old versions and OP is right.It is giving the wrong output.It is giving correct one in only version 36.0.

EDIT2:

Just checked the latest release notes and found this:

A block of test code enclosed by the Test.startTest() and Test.stopTest() methods now reliably receives its own block of governor limits. Test.startTest() stores your per-transaction limit counters and temporarily resets them to zero. Test.stopTest() restores your limit counters to pre-Test.startTest() values. When your test method finishes, all per-transaction limits reset to zero. Previously, some limits, such as for SOQL queries, didn’t always reset inside a Test.startTest()/Test.stopTest() block.

So finally we have full proof reason :)

EDIT3:

It's becoming interesting.

I just ran this changed code in old version and found that it hits the soql limit.

for (integer i = 0; i < 100; i++){//running the 100 cycles of loop
        List <account> accts = [select name from Account];
    }
    Test.startTest();
    List <account> accts = [select name from Account];
    system.debug('made it here');
    Test.stopTest();
    system.debug('done');
3
  • what api version? Commented May 6, 2016 at 5:30
  • 1
    i was at api v 31 Commented May 6, 2016 at 5:37
  • see my updated answer.It is giving correct output in version 36.
    – Mr.Frodo
    Commented May 6, 2016 at 6:23
2

The correct way to observe such limits is in context.

// 99 queries
Test.startTest();
    system.assertEquals(0, Limits.getQueries());
    // additional query
    system.assertEquals(1, Limits.getQueries());
Test.stopTest();
system.assertEquals(99, Limits.getQueries());

The same holds for other governor limits you wish to rest. Email invocations, DML statements, etc. Note that the value gets reset (to its prior state, not zero) when you call stopTest, so often the last thing you do before such call is cache the limit value.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .