[SalesForce] Sudden MIXED_DML_OPERATION errors without code changes

So I have 3 orgs that are basically all on the same codebase. On the production org (the one that gets changed the least) some of the tests are suddenly failing – all with the same error message:

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): User, original object: S2XTransaction: []

First of all РI have no clue what S2XTransaction is but it must be some kind of internal Salesforce object. Second Рthese tests are kinda like Schr̦dinger's cat because when I run them and check their results they are failing. If all the tests are run as part of the deployment of a changeset Рall of them are passing! Over 90% of the classes haven't been touched in the last couple of years Рso why is this error suddenly occurring? And why only on 1 out of 3 orgs? And even then why does it only happen when I run the tests directly?

So far my reasoning is this: Something must have been changed as there were no problems about 6 weeks ago. The code wasn't changed much and there was almost nothing that was deployed from the two other orgs to production. And even then all the changes were small, not affecting the now failing classes in any way. Right now my guess is that it could have something to do with this New user permission to view user roles and hierarchy change that got auto-activated at the beginning of the year.

The code that is actually failing in every test looks like this:

// This line below is failing
System.runAs(getTestAdminUser()) {
    // Run some code
}

// Just getting the test user
public static User getTestAdminUser() {
    User user = new User();

    // Set properties
    user.Alias = 'admin';

    return user;
}

I'm actually not quite sure what I'm even looking for. This is so confusing and I really hope somebody can shed some light on this.

Best Answer

Calling system.runAs is a DML Statement. It inserts the record if it's not already in the database, which looks like your current setup. You should query for your admin user instead.

static User getAdminUser()
{
    return [SELECT Id FROM User WHERE Profile.Name = 'System Administrator'];
}
Related Topic