First, you'll want to create your RunAs user who should be someone with the profile that has the permissions needed to create accounts and enable your contacts as portal users. Worst case, that can always be a System Administrator.
I usually create a Test Class Utility in most orgs that creates an Admin User for me and a "Standard User" to use for testing. It will have methods that look something like below:
/** a default user to use in System.runAs() */
private static User tstRnnr {
get {
if (null == tstRnnr) {
// all test code should execute under a user we can control so as to avoid
// surprises when deploying to different environments.
UserRole[] roles = [SELECT Id FROM UserRole WHERE DeveloperName = 'Administrator'];
if (roles.isEmpty() == true) {
roles.add(new UserRole(DeveloperName = 'Administrator', Name = 'r0'));
insert roles;
}
tstRnnr = new User(Alias = 'tstr01', Email='tstr01@theOrg.com', EmailEncodingKey='UTF-8', FirstName= 'TstrFrst', LastName='TstrLst01', LanguageLocaleKey='en_US', LocaleSidKey='en_US', TimeZoneSidKey='America/Los_Angeles', UserName='tstt01@theOrg.com');
testRunner.UserRoleId = roles[0].Id;
insert tstRnnr;
}
return tstRnnr;
}
private set;
}
As I noted, I'll do the same or similar for a user with a Standard profile
Once you have your RunAs user, a portal user needs to be created by first creating an Account, then a related contact. Once you do that, you can finally create the portal user. An account needs an own, so in the class below, I created users who would be owners. In this test class the owner of the portal user was going to be changed at a later time. I used code that looks something like below:
/* Use RunAs to create new Users with assigned profiles and roles */
integer smpl = 4; // can increase this to up to 200 or set as low as 1
system.RunAs(U0){
/* Create Users for Old Owners */
for(i=0;i<smpls;i++){
User u2 = new User(Alias = 'standto'+(string.valueOf(i))+'', Email='tstusro'+(string.valueOf(i))+'@thOrg.com',
EmailEncodingKey='UTF-8', FirstName= 'TstFrstO', LastName='TstLstO'+(string.valueOf(i))+'', LanguageLocaleKey='en_US',
LocaleSidKey='en_US', ProfileID = U1.ProfileID, UserRoleId=U1.UserRoleId,
TimeZoneSidKey='America/Los_Angeles', UserName='tstusro'+(string.valueOf(i))+'@theOrg.com');
OwnrOld.add(u2);
}
if(OwnrOld.IsEmpty() == false){
Database.SaveResult[] OwnrOldInsrtRslts = Database.Insert(OwnrOld,true);
for(Database.SaveResult ooir: OwnrOldInsrtRslts){
if(ooir.IsSuccess()){
ooirIds.add(ooir.getId());
}
}
system.assertEquals(ooirIds.size(),(smpls));
}
}// end System.RunAs(U0)
Now, on to creating the portal users...
/* Use RunAs to create new Portal Users with High Volume Portal User Profiles */
system.RunAs(U0){
/* Create Accts for Portal User Contacts to establish ownership & link to a role */
for(i=0;i<smpls;i++){
Account CEact = new Account(Name= 'PAcctO'+ String.valueOf(i)+'', Is_Active__c = true, Region__c = 'SouthEast', OwnerID = U1.Id );
CEActs.add(CEact);
}
/* insert the new Accts */
if(CEActs.IsEmpty() == false){
Database.SaveResult[] CEActsInsrtRslts = Database.Insert(CEActs,true);
/* Get CE Accts Id's */
for(Database.SaveResult actsr: CEActsInsrtRslts ){
if(actsr.IsSuccess()){
CEAID.add(actsr.getId());
}
}
system.assertEquals(CEAID.size(),(smpls));
}// End if(CEActs.IsEmpty()
/* verify save results & put into a map */
map<Id,Account> CEACTmap = new map<Id,Account>([select Id, Name, OwnerID, Region__c from Account where Id =: CEAID]);
/* Create Portal User Contacts */
for(x=0;x<smpls;x++) {
Contact CECtc = new Contact( AccountID = CEActs[x].Id, FirstName = 'PrtlFrst0', LastName = 'PrtlLstO'+ String.valueOf(x)+'', Phone = '727-755-111'+string.valueOf(x)+'', MailingStreet = '11'+String.valueOf(x) +' Prtl0'+ String.valueOf(x)+' St', MailingCity = 'PortalCty0'+String.valueOf(x)+'', MailingState = 'FL', MobilePhone = '757-743-111'+String.valueOf(x)+'', Email='portalo'+string.valueOf(x)+'@PortalTest.com' );
CECtcs.add(CECtc);
}
/* insert the new Ctcs */
if(CECtcs.IsEmpty() == false){
Database.SaveResult[] CECtcsInsrtRslts = Database.Insert(CECtcs,true);
/* Get CE Contact Id's */
for(Database.SaveResult ctcr: CECtcsInsrtRslts ){
if(ctcr.IsSuccess()){
CIDs.add(ctcr.getId());
}
}
system.assertEquals(CIDs.size(),smpls);
}// End if(CECtcs.IsEmpty()
/* verify save results and put into a map */
map<Id,Contact> CECTCmap = new map<Id,Contact>([select Id, AccountID, FirstName, LastName, Phone, MobilePhone from Contact where Id =: CIDs]);
/* Create Portal Users */
system.assertEquals(CECTCmap.keySet().size(),smpls);
for(i=0;i<smpls;i++){
User u6 = new User(ContactID = CECtcs[i].Id, Alias = 'PrtlUsr'+(string.valueOf(i))+'', Email= CECtcs[i].Email,
EmailEncodingKey='UTF-8', FirstName= CECtcs[i].FirstName, LastName= CECtcs[i].LastName, TimeZoneSidKey='America/Chicago',
LanguageLocaleKey='en_US', LocaleSidKey='en_US', MobilePhone = CECtcs[i].MobilePhone, Phone = CECtcs[i].Phone,
userName=CECtcs[i].Email, ProfileID = U5.ProfileID);
PrtlUsrs.add(u6);
}
if(PrtlUsrs.IsEmpty() == false){
Database.SaveResult[] PrtlUsrsInsrtRslts1 = Database.Insert(PrtlUsrs,true);
for(Database.SaveResult pu1sr: PrtlUsrsInsrtRslts1){
if(pu1sr.IsSuccess()){
PUIDs.add(pu1sr.getId());
}
}//end for
system.assertEquals(PUIds.size(),smpls);
}// end if(PrtlUsrs.IsEmpty()
}// end System.RunAs(U0)
This code didn't cause any mixed DML errors.
Best Answer
It is the Owner of the Account the Portal User Contact record that needs to have the role. The HVP User will inherit the role hierarchy from the Accounts Owners profile. First, create the user that will own the account, and make sure they have a Role. Then create the Account, owned by this user, then, the contact related to the account. Last, create the HPU and include the contactid of the contact you created. Then, use it for your test.