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:
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.