You need to sign in to do that
Don't have an account?
XactiumBen
MIXED_DML_OPERATION in TestMethods
I am trying to create a testmethod for a trigger but I'm running into MIXED_DML_OPERATION error in the Salesforce Run Tests UI.
What I do is create an EmailTemplate object in the test (just in case a certain org doesn't have any EmailTemplate records) then creating a Case which fires the trigger.
In Eclipse I get 100% code coverage (plus no errors) but in the Salesforce UI I get the MIXED_DML_OPERATION error. Is there any way to fix this issue, like define inserting the EmailTemplate as a setup task that has nothing do to with how my trigger performs?
Hey
We've just found a workaround for this issue. Although the workaround contains a salesforce bug, and we had to create a workaround for that too. We spoke to salesforce about it and logged a case but no info back yet. The workaround is liek this
@future private static void insertEmailTemplates(String emailTemplateName){ Folder myFolder = [select id from Folder where developerName = :emailTemplateFolder]; folderId = myFolder.id; List<EmailTemplate> listEmailTemplate = [select id from EmailTemplate where folderId = :folderId]; delete listEmailTemplate; EmailTemplate mailTemplate= new EmailTemplate(folderId = myFolder.id, body='yo', developerName=emailTemplateName, name=emailTemplateName,TemplateType='Text', subject='yo', isactive=true, encoding='UTF-8' ); insert mailTemplate; } public static void initEmailTemplates(String emailTemplateName){ if(user==null){ Integer countUser = [select count() from User]; if(countUser == 1){ user = new User(); user.Username = 'test2@us.xyz.com'; user.LastName = 'Last2TestName'; user.Email = 'test2@us.xyz.com'; user.alias = 'testA2'; user.TimeZoneSidKey = 'America/New_York'; user.LocaleSidKey = 'en_US'; user.EmailEncodingKey = 'ISO-8859-1'; user.ProfileId = [select id from Profile where Name='System Administrator'].Id; user.LanguageLocaleKey = 'en_US'; System.debug('getLimitRunAs: '+Limits.getLimitRunAs()); }else{ user = [select Username ,LastName,Email,alias,TimeZoneSidKey,LocaleSidKey,EmailEncodingKey,ProfileId,LanguageLocaleKey from User where id !=:UserInfo.getUserId() LIMIT 1]; } System.runAs(user){ Test.startTest(); insertEmailTemplates(emailTemplateName); Test.stopTest(); } } }
So what's happening here is you're inserting emailtemplates in a different context by using @future. Except that there is a bug and this doesn't actually happen so you have to use a runAs() with the @future method for it to work. The Test.startTest() and Test.stopTest() force the asynchronous @future method to work 'synchronously'.
This works for me everywhere except in managed-released packages where I have to tweak it a bit.
Good luck
Wes
All Answers
Hey
We've just found a workaround for this issue. Although the workaround contains a salesforce bug, and we had to create a workaround for that too. We spoke to salesforce about it and logged a case but no info back yet. The workaround is liek this
@future private static void insertEmailTemplates(String emailTemplateName){ Folder myFolder = [select id from Folder where developerName = :emailTemplateFolder]; folderId = myFolder.id; List<EmailTemplate> listEmailTemplate = [select id from EmailTemplate where folderId = :folderId]; delete listEmailTemplate; EmailTemplate mailTemplate= new EmailTemplate(folderId = myFolder.id, body='yo', developerName=emailTemplateName, name=emailTemplateName,TemplateType='Text', subject='yo', isactive=true, encoding='UTF-8' ); insert mailTemplate; } public static void initEmailTemplates(String emailTemplateName){ if(user==null){ Integer countUser = [select count() from User]; if(countUser == 1){ user = new User(); user.Username = 'test2@us.xyz.com'; user.LastName = 'Last2TestName'; user.Email = 'test2@us.xyz.com'; user.alias = 'testA2'; user.TimeZoneSidKey = 'America/New_York'; user.LocaleSidKey = 'en_US'; user.EmailEncodingKey = 'ISO-8859-1'; user.ProfileId = [select id from Profile where Name='System Administrator'].Id; user.LanguageLocaleKey = 'en_US'; System.debug('getLimitRunAs: '+Limits.getLimitRunAs()); }else{ user = [select Username ,LastName,Email,alias,TimeZoneSidKey,LocaleSidKey,EmailEncodingKey,ProfileId,LanguageLocaleKey from User where id !=:UserInfo.getUserId() LIMIT 1]; } System.runAs(user){ Test.startTest(); insertEmailTemplates(emailTemplateName); Test.stopTest(); } } }
So what's happening here is you're inserting emailtemplates in a different context by using @future. Except that there is a bug and this doesn't actually happen so you have to use a runAs() with the @future method for it to work. The Test.startTest() and Test.stopTest() force the asynchronous @future method to work 'synchronously'.
This works for me everywhere except in managed-released packages where I have to tweak it a bit.
Good luck
Wes
Thanks for that work around. I made it a little bit easier by not getting a user out of the database but instead doing this:
System.runAs(new User(Id = System.UserInfo.getUserId())){ Test.startTest(); insertEmailTemplates(emailTemplateName); Test.stopTest(); }
This still seems to work :D