[SalesForce] MIXED_DML_OPERATION, DML operation error when creating user role record in test class

I have a class wherein I am inserting two different records at the same time. These records are for a custom setting object named Setting__c and a custom
object named Item__c. This works well and behaves accordingly.

Meanwhile, I created a test class for this but I am encountering this error:

System.DmlException: Insert failed. First exception on row 0; first
error: MIXED_DML_OPERATION, DML operation on setup object is not
permitted after you have updated a non-setup object (or vice versa):
Item__c, original object: UserRole: []

I needed to cover the line for pertaining to the user role object. How can I resolve this?

Apex Class:

public class SettingClass {

    private ApexPages.StandardController con;
    public Setting__c settingRec {get;set;}
    public List<SettingWrapper> swraplist {get;set;} 
    public Integer rowToRemove {get;set;}
    public String selectedRole {get;set;}
    public String selectedStat {get;set;}

    public SettingClass(ApexPages.StandardController controller) {
        con = controller;
        this.settingRec = (Setting__c)controller.getRecord();
        swraplist = new List<SettingWrapper>();
        addNewRow();

    }
    public void addNewRow() {
        List<SettingWrapper> temp_wrap = new List<SettingWrapper>();
        SettingWrapper newSetting = new SettingWrapper();

        Item__c newItemRecord = new Item__c();      
        newSetting.set1 = newItemRecord;
        newSetting.index = temp_wrap.size();
        temp_wrap.add(newSetting);
        for(SettingWrapper sw : temp_wrap) {
            swraplist.add(sw);
        }
    }

    public void removeRow() {
        List<SettingWrapper> rem_wrap = new List<SettingWrapper>();
        for(SettingWrapper sw : swraplist) {
            rem_wrap.add(sw);
        }
        rem_wrap.remove(rowToRemove);
        swraplist.clear();
        for(SettingWrapper sw2 : rem_wrap) {
            swraplist.add(sw2);
        }
    }

    public List<SelectOption> getUserRoleList() {
        List<UserRole> urList = [SELECT Id, Name FROM UserRole];
        List<SelectOption> urOptionList = new List<SelectOption>();
        urOptionList.add(new SelectOption(' ',' '));

        for(UserRole ur : urList) {
            urOptionList.add(new SelectOption(ur.Id, ur.Name));    
        }

        return urOptionList;
    }

    public List<SelectOption> getStatList() {
        List<SelectOption> statOptionList = new List<SelectOption>();
        Schema.DescribeFieldResult statResults = Account.Status__c.getDescribe();

        List<Schema.PicklistEntry> ple = statResults.getPicklistValues();

        for(Schema.PicklistEntry f : ple) {
            statOptionList.add(new SelectOption(f.getLabel(), f.getValue()));    
        }  

        return statOptionList;
    }

    public PageReference save() {

        List<SettingWrapper> swList = new List<SettingWrapper>();
        List<Item__c> newItemList = new List<Item__c>();


        for(SettingWrapper sw : swraplist) {
            swList.add(sw);
        }

        UserRole ur = [SELECT Id, Name FROM UserRole WHERE Id =: selectedRole];  

        Setting__c newSetting = new Setting__c();

        newSetting.Name = settingRec.Name;
        newSetting.Status__c = selectedStat;
        newSetting.Role_ID__c = selectedRole;
        newSetting.Role_Name__c = ur.Name;

        insert newSetting;

        if(swList !=null && !swList.isEmpty()) {

            for(SettingWrapper sRec : swList) {

                Item__c iTemp = new Item__c();
                iTemp.Lookup__c = iTemp.set1.Lookup__c; 
                iTemp.Setting__c = newSetting.Id; 
                newItemList.add(iTemp);
            }
        }

        if(!newItemList.isEmpty()) {
                insert newItemList;
        }    

        PageReference pageref = new PageReference('/' + newSetting.Id);
        pageref.setRedirect(true);
        return pageref;
    }

    public class SettingWrapper {

        public Integer index {get;set;}
        public Setting__c set1 {get;set;}

    }

}

Test Class:

@isTest
public class SettingClassTest {
    private static testMethod void InsertSettingRecord() {

        List<Setting__c> settingList = new List<Setting__c>();
        List<SettingClass.SettingWrapper> settingWrapper = new List<SettingClass.SettingWrapper>();
        Integer rowToRemove = 0;
        String selectedRole;

        SettingClass sc = new SettingClass(new ApexPages.StandardController(new Setting__c()));

        sc.getUserRoleList();
        con.getStatList();

        UserRole urole;
        System.runAs(new User(Id=UserInfo.getUserId()) {
          urole = new UserRole();
          urole.Name = 'New Role';
          insert urole;
        }

        selectedRole = urole.Id;

        List<Lookup__c> lookupList = new List<Lookup__c>();
        Lookup__c lk = new Lookup__c();
        lk.Name = 'Lookup 1';
        lookupList.add(lk);

        insert lookupList;
        System.assertequals(lookupList + '', 'lookupList');

        Test.startTest();

        Setting__c s = new Setting__c();
        s.Name = '1';
        s.Status__c = 'Status 1';
        s.Role_ID__c = selectedRole; 
        s.Role_Name__c = urole.Name;
        settingList.add(s);

        insert settingList;   
        System.assertequals(settingList + '', 'settingList');

        PageReference pg = Page.SettingPage;
        Test.setCurrentPage(pg);
        ApexPages.StandardController pgCon = new ApexPages.StandardController(ad); 
        SettingClass sClass = new SettingClass(pgCon);

        sClass.addNewRow(); 
        sClass.rowToRemove = 1;
        sClass.removeRow();

        SettingClass.SettingWrapper setWrap = new SettingClass.SettingWrapper();

        for(Integer i=0; i<200; i++) {
            Item__c newItem = new Item__c();
            newItem.Lookup__c = lk.Id;
            newItem.Setting__c = s.Id;    
            setWrap.set1 = newItem;
            setWrap.index = 0;
            settingWrapper.add(setWrap);
        }

        PageReference pg1 = Page.SettingPage;
        Test.setCurrentPage(pg1); 
        ApexPages.StandardController pgCon1 = new ApexPages.StandardController(ad);
        SettingClass sClass2 = new SettingClass(pgCon1);

        for(SettingClass.SettingWrapper setWrap2 : settingWrapper) {
            sClass2.swraplist.remove(0);
            sClass2.swraplist.add(swrap);
        }

        sClass2.save(); 

        Test.stopTest();
    }   

}

Best Answer

You can't mix UserRole and other Setup objects with things like CustomObject__c and other non-Setup objects. The way to get around this is mentioned in the documentation; use System.runAs around the Setup objects to avoid the mixed DML error.

For example, the role should be inserted like this:

UserRole urole;
System.runAs(new User(Id=UserInfo.getUserId()) {
    urole = new UserRole();
    urole.Name = 'New Role';
    insert urole;
}

Be careful, though, as System.runAs uses up a DML operation and DML row each time you call it, so avoid using it more than necessary.

Related Topic