0

I'm writing a test class where i have to create a user first and after run test as that user. My code is:

@isTest static void test() {
        //create a USer to run the test
        Account a = new Account(Name='Test Account Name');
        insert a;
        Contact cont = new Contact(LastName = 'Contact Last Name', AccountId = a.id);
        insert cont;
        //UserRole ruolo=[select id from UserRole where Name='CEO'];
        User user = new User();
        user.ProfileID = [Select Id From Profile Where Name='System Administrator'].id;
        user.UserRoleid=[select Id from UserRole where Name='CEO'].Id;
        user.EmailEncodingKey = 'ISO-8859-1';
        user.LanguageLocaleKey = 'en_US';
        user.TimeZoneSidKey = 'America/New_York';
        user.LocaleSidKey = 'en_US';
        user.FirstName = 'username';
        user.LastName = 'lastname';
        user.Username = '[email protected]';   
        user.CommunityNickname = 'testUser123';
        user.Alias = 't1';
        user.Email = '[email protected]';
        user.IsActive = true;
        user.ContactId = cont.Id;
        insert user;
        System.RunAs(user) {            
            Test.StartTest();
            myfunction();
            Test.StopTest();
        }
    }   
        @future
        static void  myfunction(){  

            //ADDRESS
            .......
            }

but the System gives the error "Mixed DML Operation", i don't know how to handle it. Please help me

1

2 Answers 2

4

Salesforce's own docs explain this issue pretty thoroughly:

Mixed DML Operations in Test Methods

Test methods allow for performing mixed Data Manipulation Language (DML) operations that include both setup sObjects and other sObjects if the code that performs the DML operations is enclosed within System.runAs method blocks. You can also perform DML in an asynchronous job that your test method calls. These techniques enable you, for example, to create a user with a role and other sObjects in the same test.

The setup sObjects are listed in sObjects That Cannot Be Used Together in DML Operations.

Example: Mixed DML Operations in System.runAs Blocks

This example shows how to enclose mixed DML operations within System.runAs blocks to avoid the mixed DML error. The System.runAs block runs in the current user’s context. It creates a test user with a role and a test account, which is a mixed DML operation.

@isTest
private class MixedDML {
    static testMethod void mixedDMLExample() {  
        User u;
        Account a;
        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
       // Insert account as current user
        System.runAs (thisUser) {
            Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
            UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
            u = new User(alias = 'jsmith', email='[email protected]', 
                emailencodingkey='UTF-8', lastname='Smith', 
                languagelocalekey='en_US', 
                localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
                timezonesidkey='America/Los_Angeles', 
                username='[email protected]');
            insert u;
            a = new Account(name='Acme');
            insert a;
        }
    }
}

Use @future to Bypass the Mixed DML Error in a Test Method

Mixed DML operations within a single transaction aren’t allowed. You can’t perform DML on a setup sObject and another sObject in the same transaction. However, you can perform one type of DML as part of an asynchronous job and the others in other asynchronous jobs or in the original transaction. This class contains an @future method to be called by the class in the subsequent example.

public class InsertFutureUser {
    @future
    public static void insertUser() {
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
        User futureUser = new User(firstname = 'Future', lastname = 'User',
            alias = 'future', defaultgroupnotificationfrequency = 'N',
            digestfrequency = 'N', email = '[email protected]',
            emailencodingkey = 'UTF-8', languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, 
            timezonesidkey = 'America/Los_Angeles',
            username = '[email protected]',
            userpermissionsmarketinguser = false,
            userpermissionsofflineuser = false, userroleid = r.Id);
        insert(futureUser);
    }
}

This class calls the method in the previous class.

@isTest
public class UserAndContactTest {
    public testmethod static void testUserAndContact() {
        InsertFutureUser.insertUser();
        Contact currentContact = new Contact(
            firstName = String.valueOf(System.currentTimeMillis()),
            lastName = 'Contact');
        insert(currentContact);
    }
}
1

You cannot insert setup and non-setup object in a single instance so use the below code to avoid the MIXED DML Error.

static void createTEstData() {
            //UserRole ruolo=[select id from UserRole where Name='CEO'];
            User user = new User();
            user.ProfileID = [Select Id From Profile Where Name='System Administrator'].id;
            user.UserRoleid=[select Id from UserRole where Name='CEO'].Id;
            user.EmailEncodingKey = 'ISO-8859-1';
            user.LanguageLocaleKey = 'en_US';
            user.TimeZoneSidKey = 'America/New_York';
            user.LocaleSidKey = 'en_US';
            user.FirstName = 'username';
            user.LastName = 'lastname';
            user.Username = '[email protected]';   
            user.CommunityNickname = 'testUser123';
            user.Alias = 't1';
            user.Email = '[email protected]';
            user.IsActive = true;
            user.ContactId = cont.Id;
            insert user;

            System.RunAs(new User(Id = UserInfo().getUserId())) {
                //create a USer to run the test
                Account a = new Account(Name='Test Account Name');
                insert a;
                Contact cont = new Contact(LastName = 'Contact Last Name', AccountId = a.id);
                insert cont;
            }
        }

        @isTest static void testFunction() {
            createData();

            //test your logic here
        }

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