[SalesForce] Problem creating HVCP unit test users for test class

I'm having a problem creating High Volume Customer Portal Users for unit testing of triggers and other code. When I attempt to create them, I'm getting an error message as follows:

System.DmlException: Insert failed. First exception on row 0; first
error: UNKNOWN_EXCEPTION, portal account owner must have a role: []

The same error is documented in a blog post by Jeff Douglass dating back to Sept 2010. I'm wondering if anything has changed. The solution at that time was to assign either the contact owner's role to the contact or the portal owner's role to the contact (sheesh, we're talking an Admin role!) when creating the User.

That should work fine for testing (will know more later today), but I'm uncomfortable with that solution for implementation of the portal. Note: we've not seen this in actual testing of the site; instead, only in unit testing but that could be because we've been the one's creating the Users as opposed to "Guests" using Self-Service.

Have you encountered this problem and if so, what was your solution to this issue?

Edit

Thanks Ralph, apparently it's time for me to post some code. I'd already been using "RunAs" to try and create the portal users. Perhaps there's something in my code, or one of the permutations I've tried, that's missing. I've even gone so far as to specify a user Id to make certain I had a user with the correct profile and role to create the portal users, but I continue to get the same error message. Here's the essence of the code I've been using:

Indeed, the solution was to create an account first for each portal user and associate that Acct with an Owner who had a Role! Portal users are definitely far more complex to create than regular users!

Final Code

User U0 = [SELECT Id, Name, UserRoleId, ProfileId, Username FROM User WHERE IsActive = True AND (Profile.Name = 'System Administrator') AND (UserRole.Name = 'Admin') limit 1];

User U5 = [SELECT Id, Name, ProfileID, Username FROM User WHERE IsActive = True AND (Profile.Name = 'High Volume Customer Portal User') limit 1];

system.RunAs(U0){

   for(i=0;i<10;i++){
      Account CEAct = new Account(Name= 'PAcctO'+ String.valueOf(x)+'', 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);

   /* Create Portal User Contacts */

   for(x=0;x<10 ;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', Position__c = 'Ambassador', MobilePhone = '757-743-111'+String.valueOf(x)+'', Email='portalo'+string.valueOf(x)+'@kubetst.com' );

      CECtcs.add(CECtc);
   }

   /* insert the new Ctcs */

   if(CECtcs.IsEmpty() == false){

      Database.SaveResult[] CECtcsInsrtRslts = Database.Insert(CECtcs,true);

   }// End if(CECtcs.IsEmpty()   

    /* Create Portal Users */ 

   for(i=0;i<10;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);

   }// end if(PrtlUsrs.IsEmpty()

}// end System.RunAs(U0)

I'm wondering if there's a required field I'm missing or if portal users need to be created using a different method than what I've used above in order to be successful? Oh, and I have the "see all data" flag enabled in the test method.

Best Answer

When you're creating the contact and accounts for the portal user in your test they're going to have whoever's running the test or whichever user is specified in a system.runas() block. The key is to make sure that user has a role and then you should be fine. It's best to create a user in your test for this and then put the portal user creation inside a system.runas() block, since you won't have to worry about whether the user running your test has a role. As for which role, any non-portal role should do.

Outside of the test code. You'll want to make sure which that users in your organization have roles. Otherwise they'll get a similar error if they create portal user (or take an action that will create a portal user via a trigger or other mechanism)