I know this seems like a really stupid question. But I am still often amazed by the SalesForce platform. Consider the following test:

static testMethod void testLimitDmlStatements()
{
    SObject record; // custom object set up elsewhere
    Test.startTest();
        insert record;
        system.assertEquals(1, Limits.getDmlStatements());
    Test.stopTest();
}

I somehow get an assertion error:

System.AssertException: Assertion Failed: Expected: 1, Actual: 0

The documentation on the Limits Class states:

getDMLStatements()

Returns the number of DML statements (such as insert, update or the database.EmptyRecycleBin method) that have been called.

How is it possible that inserting a record would not count as a DML Statement? I have a similar update test and the same assertion fails. Strangely enough, if I add another operation, the count does increment.

static testMethod void testLimitDmlStatements()
{
    SObject record; // custom object set up elsewhere
    Test.startTest();
        insert record;
        SObjectFactory.create(User.sObjectType); // inserts a User
        system.assertEquals(1, Limits.getDmlStatements());
    Test.stopTest();
}

The above test passes, as does the below...

static testMethod void testLimitDmlStatements()
{
    SObject record; // custom object set up elsewhere
    Test.startTest();
        system.assertEquals(0, Limits.getDmlStatements());
        insert record;
        system.assertEquals(1, Limits.getDmlStatements());
    Test.stopTest();
}
  • If you perform an assert after Test.stopTest() do your results differ? – Mark Pond May 19 '15 at 23:59
  • You are inserting a generic sObject, which isn't anything outside of code. Have you tried this with a concrete sObject? – greenstork May 20 '15 at 0:02
  • @greenstork Concrete type doesn't change anything. – Adrian Larson May 20 '15 at 0:08
  • Is the record being inserted something like a custom setting? It really shouldn't matter, but what logging level are you using? – Daniel Ballinger May 20 '15 at 0:49
  • @DanielBallinger DEBUG across the board but it didn't work with FINEST either. – Adrian Larson May 20 '15 at 0:52
up vote 4 down vote accepted

If the list to operate on is empty, it doesn't count as an operation. In older releases, empty lists still counted against governor limits, but this is no longer true. The DML statement becomes a noop. This old behavior is the reason why you'll often see code like "if(!mylist.isEmpty() update mylist;" Also, you can combine up to ten types of records into a single Sobject list, and it only counts as a single statement. The records in the list should be grouped together, as you'll get an error if there are more than ten chunks. Each chunk is a contiguous set of the same Sobject type. The ten thousand record limit still applies normally.

  • Yes, I've used chunking and empty lists before and those are nice features. But I am operating on a single record, not a collection. – Adrian Larson May 20 '15 at 0:05
  • Also, that's pretty cool about the limits implications of chunking. I always assumed it would count for one per sObjectType. What happens if there are 11 types? – Adrian Larson May 20 '15 at 0:10
  • If you're operating on a null object, I guess that should noop, too. Exceeding ten chunks gives a too many chunks exception. – sfdcfox May 20 '15 at 0:32
  • I think that would throw a NullPointerException, but it is not null regardless. – Adrian Larson May 20 '15 at 0:52
  • 2
    @AdrianLarson I just had an epiphany. The first line of executable code after Test.startTest() sets the context for the method's testing section (everything up to Test.stopTest()). Therefore, if the first thing you do is perform a DML operation, it simulates the DML as if it were coming from the API (in other words, the outer shell of a transaction), which doesn't count against governor limits (try placing that assert within a trigger, and upload a record via the API, you'll see what I'm talking about). If the DML statement comes from anywhere else, it does count. – sfdcfox May 20 '15 at 18:00

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.