Newer Version Available
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.
1@isTest
2private class MixedDML {
3 static testMethod void mixedDMLExample() {
4 User u;
5 Account a;
6 User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
7 // Insert account as current user
8 System.runAs (thisUser) {
9 Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
10 UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
11 u = new User(alias = 'jsmith', email='jsmith@acme.com',
12 emailencodingkey='UTF-8', lastname='Smith',
13 languagelocalekey='en_US',
14 localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
15 timezonesidkey='America/Los_Angeles',
16 username='jsmith@acme.com');
17 insert u;
18 a = new Account(name='Acme');
19 insert a;
20 }
21 }
22}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.
1public class InsertFutureUser {
2 @future
3 public static void insertUser() {
4 Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
5 UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
6 User futureUser = new User(firstname = 'Future', lastname = 'User',
7 alias = 'future', defaultgroupnotificationfrequency = 'N',
8 digestfrequency = 'N', email = 'test@test.org',
9 emailencodingkey = 'UTF-8', languagelocalekey='en_US',
10 localesidkey='en_US', profileid = p.Id,
11 timezonesidkey = 'America/Los_Angeles',
12 username = 'futureuser@test.org',
13 userpermissionsmarketinguser = false,
14 userpermissionsofflineuser = false, userroleid = r.Id);
15 insert(futureUser);
16 }
17}This class calls the method in the previous
class.
1@isTest
2public class UserAndContactTest {
3 public testmethod static void testUserAndContact() {
4 InsertFutureUser.insertUser();
5 Contact currentContact = new Contact(
6 firstName = String.valueOf(System.currentTimeMillis()),
7 lastName = 'Contact');
8 insert(currentContact);
9 }
10}