DML operations on certain sObjects, sometimes referred to as setup objects, can't be mixed with DML on other sObjects in the same transaction. This restriction exists because some sObjects affect the user’s access to records in the org. You must insert or update these types of sObjects in a different transaction to prevent operations from happening with incorrect access-level permissions. For example, you can’t update an account and a user role in a single transaction.
Let's see how to fix the MIXED_DML_OPERATION error
One option is to use @future method but since that's for running in background, we cannot query that data in the next line due to it could be created or not.
Another solution is to insert setup objects such as User using the current user during the execution. We choose this one since we can access the user later in the test
System.runAs(new User(Id = UserInfo.getUserId())){ createUser(); }
@isTest
public class TestTest {
@isTest static void itDoesNotWork() {
createUser();
createAccount();
}
@isTest static void itWorks() {
System.runAs(new User(Id = UserInfo.getUserId())){ createUser(); }
User user = [SELECT Id FROM User WHERE UserName LIKE 'admin%' LIMIT 1];
createAccount();
}
private static void createAccount(){
String random = String.valueof(DateTime.now().getTime());
Account acc = new Account(Name = random);
acc.CurrencyIsoCode = 'USD';
acc.BillingCity = 'New York';
acc.BillingCountry = 'United States';
acc.BillingState = 'New York';
acc.BillingStreet = 'abc 1234';
acc.Website = 'www.google.com';
insert ACC;
}
private static void createUser(){
String random = String.valueof(DateTime.now().getTime());
Profile profile = [SELECT Id FROM Profile WHERE Name='System Administrator'];
User user = new User();
user.Email = 'random@random.com'+random;
user.UserName = 'admin@random.com'+random;
user.LastName = 'random'+random;
user.Alias = 'random';
user.ProfileId = profile.Id;
user.EmailEncodingKey='UTF-8';
user.LanguageLocaleKey='en_US';
user.LocaleSidKey='en_US';
user.TimeZoneSidKey = 'America/Los_Angeles';
insert user;
}
}
As you can see in the image below, the first test failed and the second one worked (the one running as current user)