1

I have a batch class that I want to test (with a test method) on a high data volume, higher than 200. I get a "Too many SOQL queries: 201", on a line which calls Messaging.renderStoredEmailTemplate() which is made several time for 1 record process.

So I'd like to limit the number of SOQL queries in 12 transaction.

In the documentation I see the optional 'scope' parameter of the database.executeBatch() method to limit data processing.

It looks like it doesn't work like explained:

  1. If I use 200 or 199, I fall into the "Too many SOQL queries: 201" error -
  2. If I use a lower value for scope like 100 or 150 and even 1, I get the following error:

No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.

making believe that it tries but can't recall the execute() method of my batch. This message also makes think that the scope parameter has no influence on the batch size.

How does this parameter 'scope' work? How can I get control on the Batch size ? Is it possible to perform Tests with Test methods on high data volume (> 200 records)?

Thank you for your help

  • 1
    Unfortunately tests are constrained to only call the execute method once so you gave ti setup the number of records accordingly. – Keith C Mar 23 '18 at 11:22
4

It is generally not possible to perform high data volume unit tests, because you can't typically create that many objects in an @testSetup method without encountering limits. (There may be exceptions, if you have a very low-code instance). High data volume tests are typically run in an integration sandbox on real data.

I suspect by your description that you're running your batch test with seeAllData=true, which is strongly discouraged because it makes your test fragile to data changes in your organization and unable to run in different environments.

To directly answer your question, the integer parameter to Database.executeBatch() alters the size of the List<sObject> that is passed to each invocation of execute() within the class. Lowering this number can get code to run that is struggling with limits errors. It also reduces performance, as the database has to execute more batches rather than fewer, more efficient batches, so bulkifying code is a better solution.

In a test context, you can't execute multiple batches, so this is not going to avail you.

| improve this answer | |
  • If one batch calls another batch in the finish method, you can easily execute more than one batch in a unit test (up to 5). You can also use a technique that @sfdcfox taught me where you can step through the execution of a batch (synchronously, not asynch), create a save point, then do a database rollback when inside the finish method. This allows you to continue testing multiple batches; albeit without asserting insert, update or delete results. This technique is helpful for certain use cases. – crmprogdev Mar 23 '18 at 14:37
  • I may have expressed this poorly; meaning only to refer to the limitation Keith mentioned in comments above (one call to execute()). I'd be interested in the technique you mentioned if you have a link! – David Reed Mar 23 '18 at 14:43
  • Unfortunately I don't have a link to share with you. It was a personal exchange. I had a situation where 4 different objects were being called sequentially from the same finish method of the batch by manipulating an initial state variable. Was very difficult to test. A normal unit test would execute each of them all at once following test.stoptest. – crmprogdev Mar 23 '18 at 17:25

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.