Is MIXED_DML_OPERATION in unit tests broken?

We have a nightly integration that runs all tests and reports any errors against production, currently on Winter ’19. Everything was fine until January 14th, 2019, when 13 previously passing tests started to fail with MIXED_DML_OPERATION exceptions. The exact same tests are passing in my Spring ’19 sandbox. I created a new demonstration class in my Developer Org, which is also Winter ’19, and the tests are passing there, too. Is there a documented change on MIXED_DML_OPERATION, or is a bug being fixed?


@isTest class MixedDMLError {
    @isTest static void test() {
        User u = [select Email, TimezoneSidKey, LocaleSidkey, LastName, EmailEncodingKey, ProfileId, LanguageLocaleKey from user where id = :UserInfo.getUserId()];
        u = u.clone(false);
        u.username = 'user'+math.random()+'@org.random';
        u.alias = (math.random()+'').remove('.').left(8);
        insert u;
        Account a = new Account(Name=Math.random()+'');
        insert a;
    }
}

Edit

It has been mentioned that UserRoleId might be the culprit, so I checked the source code. Here’s the actual method creating the user:

public static User createUser( String profileName,String usrName, Boolean doInsert){
    Profile pro =[SELECT Id From Profile WHERE Name = :profileName];
    User usr = new user(
        FirstName='USR_FN',
        LastName='USR_LN',
        Username=usrName,
        ProfileId=pro.Id,
        email='example@example.com',
        emailencodingkey='UTF-8',
        languagelocalekey='en_US',
        localesidkey='en_US',
        timezonesidkey='America/Los_Angeles',
        alias='USR_FN'.substring(0,1)+'USR_LN'.substring(0,1)+string.valueof( Math.random()).substring(0,3)
    );

    if(doInsert)
        insert usr;

    return usr;
}

The role is left null, so unfortunately, that does not explain the difference. Both the unit test and the utility class it calls are identical in the Sandboxes I’ve tested and Production.


Edit 2

This problem only occurs when running tests. During deployments/validations using Run All Tests or Run Specified Tests, the operation succeeds without any errors. This appears to be a bug in how tests are run.

Answer

Likely not a bug. Note from the documentation on sObjects That Cannot Be Used Together in DML Operations:

You can insert a user in a transaction with other sObjects in Apex code saved using Salesforce API version 15.0 and later if UserRoleId is specified as null.

Your unit test does not filter on this field, nor clear it out before inserting the clone.

If you are going to create a User record by cloning the running user, make sure to set UserRoleId = null before your insert call.

If you do not do so, test runs will not behave the same for each user who runs them, or if certain attributes on that user change.

Attribution
Source : Link , Question Author : sfdcfox , Answer Author : Adrian Larson

Leave a Comment