[SalesForce] Why system.runAs(currentUser) is solving mixed DML

I wrote a test class. In test setup i am creating permissionSet and other custom object data.
my test method would be like below,

testdata()
{
  user = new user(values)
  System.runAs(user)
  {
     insert permisisonset(...value...);
  }
   insert customObject_c(..values...);
}
testmethod()
{
     createdata();
     permissionHandler.updatePermisionSet(); //Initially I got mixed DML error here. but above runaA(user) help me solved.
}

i checked the log. Its pointing to the original class (insert permissionsetList) mixed DML error. After that i added another runas in test method like below,

testmethod()
{
  createData();
  System.runAs(new User(ID = UserInfo.getUserID()))
    {
         permissionHandler.updatePermisionSet(); //working fine.
    }
}

Its working. I am confused.. still its running in system context then why it got resolved by adding getUserID() in runAs context.

Any advise or comments.

Best Answer

Interesting question: you're using System.RunAs() to run exactly as the same user as before, right?

This documentation has some interesting information. After explaining the cause of the error, it says this (highlight is mine):

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.

From the System.RunAs()documentation, we know that:

The system method runAs enables you to write test methods that change the user context to an existing user or a new user

and that:

The original system context is started again after all runAs test methods complete.

I'm assuming that, the moment you do System.Runas(User u), all the permissions of the user u are re-read form the database and re-applied to the running context. I guess that would be the reason why it works. But it's just an educated guess. Unfortunately, I don't have any further documentation to support that idea.

Interestingly enough, the both links above mentions using System.RunAs() as a workaround for the mixed DML error.