Unfortunately it seems that there is some undocumented behaviour with System.runAs and creating users in Apex tests. In particular we observed, with API 45:
- If we run a test class that we do not define
without sharing
if we pass the ProfileId in the constructor to the new User, this is not saved. - If we try to set it later in a test class not defined
without sharing
after like souser1.ProfileId = [SELECT Id FROM Profile WHERE Name='Standard User'].Id
we get an error that says thatProfileId is not writeable
- If we try in a class that has a
without sharing
then we get an error when we invoke System.runAs:REQUIRED_FIELD_MISSING, Required fields are missing: [ProfileId]: [ProfileId]
Here, for example, the code of the first case:
public class UserTest {
private static User buildUser(Profile p, String username, String alias){
User user1 = new User(Alias = alias, Username=username, LastName ='LM',
Email='example@example-213213.com',
EmailEncodingKey='UTF-8',
LanguageLocaleKey='en_US',
LocaleSidKey='en_US',
TimeZoneSidKey='America/Los_Angeles');
user1.profileId = p.Id;
System.debug('Returning user '+ user1);
return user1;
}
@isTest
public static void example1(){
Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
System.debug('Using profile ' + p);
User u2 = buildUser(p, 'example1@sfdx-test.com', 'lm');
System.runAs(u2){
User u3 = buildUser(p, 'example2@sfdx-test.com','ceo');
System.runAs(u3){
System.debug([Select ID from User]);
}
}
}
}
The above example fails with:
UserTest.example1 System.SObjectException: Field is not writeable: User.ProfileId
/Users/user/Development/salesforce/sfdx-project/force-app/main/default/classes/UserTest.cls:11:1
/Users/user/Development/salesforce/sfdx-project/force-app/main/default/classes/UserTest.cls:22:1
What are the known limitations of System.runAs and why would we encounter such problems on a scratch org?